Python使用装饰器在执行单元测试时配置环境
装饰器的定义是给一个对象动态加载功能,就像打游戏时给队友上buff一样。一直以来,我对装饰器用的不多,经常会用别的方式搞定,虽然代码丑一点,但也能用。这次遇到一个特别适合装饰器的应用场景,就是执行单元测试时的环境配置。
我是用pytest做单元测试,测试入口都是一个个test_打头的函数。和unittest不一样,pytest中并没有setUp这个方法,虽然有fixture,但读人家的源码时也很少看到有人用,这次遇到问题发现,我靠,就是加个装饰器的事,可以把setUp和tearDown一起做了,何必多此一举。
应用场景用个demo举例,由于生产环境和测试环境的不同,在测试环境中初始化Demo会报错,比如下面这个模块。
importsys
classDemo():
def__init__(self):
fail()
deffail():
ifsys.argv[0].split('\\')[-1].find('test')>-1:
raiseEnvironmentError(__name__)
defsuccess():
print(__name__)
定义了一个Demo类,初始化时会调用fail函数,这个函数在pytest环境下使用时会raise一个EnvironmentError。解决方案就是在这个Demo被调用时将模块中的fail函数替换为success函数。两个单元测试用例如下。
importdemo
deftest_demo():
try:
demo.Demo()
exceptExceptionase:
assertisinstance(e,EnvironmentError)
@replace#替换环境的装饰器
deftest_replace_demo():
demo.Demo()
其中,replace就是替换环境用的装饰器。装饰器代码如下。
defreplace(fun):#定义装饰器,传入函数名
_=demo.fail#保存模块中的fail,以便后面恢复
demo.fail=demo.success#更改
definner():#闭包函数
fun()
demo.fail=_#恢复模块中fail函数
returninner()
用装饰器配置单元测试环境真是优雅无比,写完后顿时腰不酸背不痛了呢。。。
装饰器的难点之一就是闭包(closure),闭包这个翻译在中文里没有很形象的对应关系,这造成了理解障碍。这种例子挺多的,就像单例模式最广泛的用途并不是提供一个的“单例”,叫“超级全局宇宙唯一变量”比较好。协程的功能里一点‘协’的作用都没有,叫“想在什么时候挂起就在什么适合挂起程”比较好。这样一想,闭包是不是叫“跨作用域包”或“脚踏两条船包”或“闭合环境打包”比较好。
闭包的一个定义是这样的:
Closuresarefunctionsthatrefertoindependent(free)variables(variablesthatareusedlocally,butdefinedinanenclosingscope).Inotherwords,thesefunctions'remember'theenvironmentinwhichtheywerecreated.
闭包的关键能力之一是获取上级作用域,另一个关键点在于python中函数是一个对象,可以传来传去,比如作为返回值。这两点结合起来就可以将函数所处的环境打包传到目标区域。在上面一个例子中inner就是一个闭包函数,它在这里的作用就是将inner函数之前的那个区域,就是第二行和第三行。
下面还有个闭包的例子,可以看到在inner外定义了a,b,在inner中使用了a,在test_closure函数实例化后可以看看其__closure__方法中的对象,这个__closure__只包含了a,并没包含b,因为b没有在inner中使用,被垃圾回收了,而a保留了下来,而a就是由于闭包的特性保留下来的,可以用pdb来看看__closure__中是否保留了b。
deftest_closure():
a,b=1,2
definner():
print(a)
returninner
close=test_closure()
print(close.__closure__[0])#
另外,python中的闭包和javascript中的闭包是一个意思,可能需要实现的功能没js中那么多,但理解python闭包时可以参考js的教程。
以上内容为大家介绍了Python使用装饰器在执行单元测试时配置环境,希望对大家有所帮助,如果想要了解更多Python相关知识,请关注IT培训机构:千锋教育。
猜你喜欢LIKE
相关推荐HOT
python gensim库是什么?
pythongensim库是什么?gensim库在文本监控里,首先在稳定上,坚如磐石,不用担心稳定性问题,其次,时效性很强,执行能力很快,经常在最重要的...详情>>
2023-11-06 21:48:19python中getattr()是什么?
python中getattr()是什么?本文教程操作环境:windows7系统、Python3.9.1,DELLG3电脑。1、getattr()用来获取对象中的属性值;获取对象object的属...详情>>
2023-11-06 21:41:07python标识符如何使用?
python标识符如何使用?为了给编程中函数、类等进行区分,会赋予它们不同的名称。我们把这种命名叫做标识符,也可以理解为符号的标记。当然这种...详情>>
2023-11-06 21:33:55Python IDE之Thonny的介绍
pythonIDE之Thonny的介绍今天要介绍的IDE,可能没用过,甚至可能没听说过。叫Thonny,是塔尔图大学开发的,适合程序员新手。它的界面很容易使用...详情>>
2023-11-06 20:54:19热门推荐
如何使用python中的help函数?
沸如何使用python的callable函数?
热python gensim库是什么?
热python中xluntils库是什么?
新python中getattr()是什么?
python中的win32com库是什么?
python标识符如何使用?
如何使用python中schedule模块?
python中ruamel.yaml模块是什么?
defaultdict在python中计算键值的和
python sleep和wait对比分析
python中字符串转成数字的几种方法
python中SocketServer是什么?
python中如何使用@contextmanage?