百科狗-知识改变命运!
--

Python使用装饰器在执行单元测试时配置环境

乐乐1年前 (2023-11-21)阅读数 30#技术干货
文章标签函数

装饰器的定义是给一个对象动态加载功能,就像打游戏时给队友上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:

Python使用装饰器在执行单元测试时配置环境

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培训机构:开发教育。

鹏仔微信 15129739599 鹏仔QQ344225443 鹏仔前端 pjxi.com 共享博客 sharedbk.com

免责声明:我们致力于保护作者版权,注重分享,当前被刊用文章因无法核实真实出处,未能及时与作者取得联系,或有版权异议的,请联系管理员,我们会立即处理! 部分文章是来自自研大数据AI进行生成,内容摘自(百度百科,百度知道,头条百科,中国民法典,刑法,牛津词典,新华词典,汉语词典,国家院校,科普平台)等数据,内容仅供学习参考,不准确地方联系删除处理!邮箱:344225443@qq.com)

图片声明:本站部分配图来自网络。本站只作为美观性配图使用,无任何非法侵犯第三方意图,一切解释权归图片著作权方,本站不承担任何责任。如有恶意碰瓷者,必当奉陪到底严惩不贷!

内容声明:本文中引用的各种信息及资料(包括但不限于文字、数据、图表及超链接等)均来源于该信息及资料的相关主体(包括但不限于公司、媒体、协会等机构)的官方网站或公开发表的信息。部分内容参考包括:(百度百科,百度知道,头条百科,中国民法典,刑法,牛津词典,新华词典,汉语词典,国家院校,科普平台)等数据,内容仅供参考使用,不准确地方联系删除处理!本站为非盈利性质站点,本着为中国教育事业出一份力,发布内容不收取任何费用也不接任何广告!)