背景:
这几天在调试之前搭建的pytest框架时,发现原框架对case中的变量进行动态替换的代码不够完美,原代码逻辑会造成代码中会出现大量的if语句,让代码量增加不少,并且后期维护也不方便:case只要新增了一个变量,就需要在通过if语句进行判断,从而实现变量替换。再发现这个问题之后,我决心优化这块代码。
首先,我们先一起分析一下我原本的代码逻辑,以及我当时实现的想法。
原本实现逻辑:
从上面流程图来看,最初的实现逻辑是将需要替换的变量分为了需要脚本生成和已经存在的变量来区分的。在环境变量多,需要脚本动态生成的数据少的前提下,该逻辑是适用的。但是如果需要脚本生成数据并赋值给变量这样的场景过多时,该方式就不适用。
具体原因如下:
1.每增加一个变量,就需要增加一个if语句,代码又臭又长。
2.代码维护不便,每增加一次变量就需要改动代码。
因此我们需要对该方法进行优化!
优化该方法的切入点就在与黄色方框标记的代码中,从上图可知,我们对mark是否存在于环境变量中进行了判断,因此我们只需要一个else,就可以解决上述问题!
优化后的实现逻辑:
对比两个流程图来看,现在的流程已经不需要单独对需要脚本生成的变量分别进行判断,从而调用方法实现赋值。基于我们目前的流程图,我们需要解决的问题是:当需要赋值的变量不是环境变量时,我们需要通过代码将其设置为环境变量,并且去获取到它的值。
那么我们需要实现一个逻辑:传入的参数或者变量,让代码根据传入的参数或者变量去决定它需要执行哪一个方法。
要实现该逻辑,我们需要使用getattr方法,优化后的代码如下:
将之前反复if判断的语句优化成了蓝色方框标记的代码优缺点如下:
**优点:**
1.后续用例中在出现新的非环境变量的变量名,不需要在通过if语句去实现数据替换
2.代码不需要反复修改
**缺点:**
1.用例中对应的变量名称需要与生成数据的方法名保持一致。具体原因见拓展。
拓展
如何通过getattr实现传入不同的参数,调用不同的方法。
def func1():
print("This is function 1.")
def func2():
print("This is function 2.")
def func3():
print("This is function 3.")
# 获取函数名
func_name = "func1"
# 根据函数名动态调用函数
getattr(__main__, func_name)()
在上述代码中,定义了三个不同的方法,然后通过getattr实现了根据函数名动态调用函数,运行结果为:“This is function 1.”,getattr() 函数的第一个参数是模块名或对象名,这里我们使用 main 表示当前模块。第二个参数是要获取的函数名(这里就是我前面提到的变量名要与方法名保持一致,因为我们实现的逻辑是:变量不是环境变量时,就基于该变量名去生成一个环境变量),这里我们使用 func_name 变量来表示。
注意!在使用getattr()根据函数名动态调用函数时,需要注意getattr(main, func_name)()与getattr(main, func_name)的区别,getattr(main, func_name)()是使用 getattr() 函数获取 main对象中指定方法名为 func_name的方法,并返回该方法对象。然后,使用函数调用语法 () 调用该方法;getattr(rd, mark) 只是获取了 rd 对象中指定方法名为 mark 的方法对象,并没有进行调用
------------------------学海无涯