头条涨薪秘籍全网没有之一的pytest玩转数据驱动测试框架
2024年1月17日 凝脂 前言:
嗨咯铁汁们,很久不见,我还是你们的老朋友,这里也感谢各位小伙伴的点赞和关注,
你们的三连是我最大的动力哈,我也不会辜负各位的期盼,这里呢给大家出了一个
我们废话少说直接开始正文
【文章的末尾给大家留下了大量的福利】
编辑
ytest架构是什么?
首先,来看一个pytest的例子:
deftesta():print(123)
collected1itemtesta。py。〔100〕1passedin0。02s
输出结果很简单:收集到1个用例,并且这条测试用例执行通过。
此时思考两个问题:
1。pytest如何收集到用例的?
2。pytest如何把python代码,转换成pytest测试用例(又称item)?
pytest如何做到收集到用例的?
这个很简单,遍历执行目录,如果发现目录的模块中存在符合pytest测试用例要求的python对象,就将之转换为pytest测试用例。
比如编写以下hook函数:
defpytestcollectfile(path,parent):print(hello,path)
helloC:UsersyuruoDesktopmpmp123mpestcaseinit。pyhelloC:UsersyuruoDesktopmpmp123mpestcaseconftest。pyhelloC:UsersyuruoDesktopmpmp123mpestcaseesta。py
会看到所有文件内容。
pytest像是包装盒,将python对象包裹起来,比如下图:
当写好python代码时:
deftesta:print(123)
会被包裹成Function:
Functiontesta
可以从hook函数中查看细节:
defpytestcollectionmodifyitems(session,config,items):pass
于是,理解包裹过程就是解开迷题的关键。pytest是如何包裹python对象的?
下面代码只有两行,看似简单,但暗藏玄机!
deftesta:print(123)
把代码位置截个图,如下:
我们可以说,上述代码是处于testcase包下的testa。py模块的testa函数,pytest生成的测试用例也要有这些信息:
处于testcase包下的testa。py模块的testa测试用例:
把上述表达转换成下图:
pytest使用parent属性表示上图层级关系,比如Module是Function的上级,Function的parent属性如下:
Functiontesta:parent:Moduletestparse。py
当然Module的parent就是Package:
Moduletestparse。py:parent:Packagetests
这里科普一下,python的package和module都是真实存在的对象,你可以从obj属性中看到,比如Module的obj属性如下:
如果理解了pytest的包裹用途,非常好!我们进行下一步讨论:如何构造pytest的item?
以下面代码为例:
deftesta:print(123)
构造pytest的item,需要:
3。构建Package
4。构建Module
5。构建Function
以构建Function为例,需要调用其fromparent()方法进行构建,其过程如下图:
,就可以猜测出,构建Function一定与其parent有不小联系!又因为Function的parent是Module:
根据下面Function的部分代码(位于python。py文件):
classFunction(PyobjMixin,nodes。Item):用于创建测试用例classmethoddeffromparent(cls,parent,kw):Thepublicconstructor。returnsuper()。fromparent(parentparent,kw)获取实例defgetobj(self):assertself。parentisnotNonereturngetattr(self。parent。obj,self。originalname)type:ignore〔attrdefined〕运行测试用例defruntest(self)None:Executetheunderlyingtestfunction。self。ihook。pytestpyfunccall(pyfuncitemself)
得出结论,可以利用Module构建Function!其调用伪代码如下:
Function。fromparent(Module)
既然可以利用Module构建Function,那如何构建Module?
当然是利用Package构建Module!
Module。fromparent(Package)
既然可以利用Package构建Module那如何构建Package?
别问了,快成套娃了,请看下图调用关系:
编辑
pytest从Config开始,层层构建,直到Function!Function是pytest的最小执行单元。
手动构建item就是模拟pytest构建Function的过程。也就是说,需要创建Config,然后利用Config创建Session,然后利用Session创建Package,,最后创建Function。
其实没这么复杂,pytest会自动创建好Config,Session和Package,这三者不用手动创建。
比如编写以下hook代码,打断点查看其parent参数:
defpytestcollectfile(path,parent):pass
如果遍历的路径是某个包(可从path参数中查看具体路径),比如下图的包:
编写如下代码即可构建pytest的Module,如果发现是yaml文件,就根据yaml文件内容动态创建Module和module:
frompytest。pythonimportModule,Packagedefpytestcollectfile(path,parent):ifpath。ext。yaml:pytestmoduleModule。fromparent(parent,fspathpath)返回自已定义的pythonmodulepytestmodule。getobjlambda:MyModulereturnpytestmodule
需要注意,上面代码利用猴子补丁改写了getobj方法,为什么这么做?
Module利用getobj方法寻找并导入(import语句)path包下的module,其源码如下:
pytestpython。pyModuleclassModule(nodes。File,PyCollector):defgetobj(self):returnself。importtestmodule()defimporttestmodule(self):Weassumeweareonlycalledoncepermodule。importmodeself。config。getoption(importmode)try:关键代码:从路径导入modulemodimportpath(self。fspath,modeimportmode)exceptSyntaxErrorase:raiseself。CollectError(ExceptionInfo。fromcurrent()。getrepr(styleshort))frome省略部分代码。。。
但是,如果使用数据驱动,即用户创建的数据文件testparse。yaml,它不是。py文件,不会被python识别成module(只有。py文件才能被识别成module)。
这时,就不能让pytest导入(import语句)testparse。yaml,需要动态改写getobj,返回自定义的module!
因此,可以借助lambda表达式返回自定义的module:
lambda:MyModule
这就涉及元编程技术:动态构建python的module,并向module中动态加入类或者函数:
importtypes动态创建modulemoduletypes。ModuleType(name)deffunctiontemplate(args,kwargs):print(123)向module中加入函数setattr(module,testabc,functiontemplate)
综上,将自己定义的module放入pytest的Module中即可生成item:
conftest。pyimporttypesfrompytest。pythonimportModuledefpytestcollectfile(path,parent):ifpath。ext。yaml:pytestmoduleModule。fromparent(parent,fspathpath)动态创建modulemoduletypes。ModuleType(path。purebasename)deffunctiontemplate(args,kwargs):print(123)向module中加入函数setattr(module,testabc,functiontemplate)pytestmodule。getobjlambda:modulereturnpytestmodule
创建一个yaml文件,使用pytest运行:
testsessionstartsplatformwin32Python3。8。1,pytest6。2。4,py1。10。0,pluggy0。13。1rootdir:C:UsersyuruoDesktopmpplugins:allurepytest2。8。11,forked1。3。0,rerunfailures9。1。1,timeout1。4。2,xdist2。2。1collected1itemtesta。yaml123。1passedin0。02sPSC:UsersyuruoDesktopmp
现在停下来,回顾一下,我们做了什么?
借用pytesthook,将。yaml文件转换成pythonmodule。
作为一个数据驱动测试框架,我们没做什么?
没有解析yaml文件内容!上述生成的module,其内的函数如下:
deffunctiontemplate(args,kwargs):print(123)
只是简单打印123。数据驱动测试框架需要解析yaml内容,根据内容动态生成函数或类。比如下面yaml内容:
testabc:print:123
表达的含义是定义函数testabc,该函数打印123。
可以利用yaml。safeload加载yaml内容,并进行关键字解析,其中path。strpath代表yaml文件的地址:
importtypesimportyamlfrompytest。pythonimportModuledefpytestcollectfile(path,parent):ifpath。ext。yaml:pytestmoduleModule。fromparent(parent,fspathpath)动态创建modulemoduletypes。ModuleType(path。purebasename)解析yaml内容withopen(path。strpath)asf:yamcontentyaml。safeload(f)forfunctionname,stepsinyamcontent。items():deffunctiontemplate(args,kwargs):函数模块遍历多个测试步骤〔print:123,print:456〕forstepdicinsteps:解析一个测试步骤print:123forstepkey,stepvalueinstepdic。items():ifstepkeyprint:print(stepvalue)向module中加入函数setattr(module,functionname,functiontemplate)pytestmodule。getobjlambda:modulereturnpytestmodule
上述测试用例运行结果如下:
testsessionstartsplatformwin32Python3。8。1,pytest6。2。4,py1。10。0,pluggy0。13。1rootdir:C:UsersyuruoDesktopmpplugins:allurepytest2。8。11,forked1。3。0,rerunfailures9。1。1,timeout1。4。2,xdist2。2。1collected1itemtesta。yaml123。1passedin0。02s
当然,也支持复杂一些的测试用例:
testabc:print:123print:456testabd:print:123print:456
其结果如下:
testsessionstartsplatformwin32Python3。8。1,pytest6。2。4,py1。10。0,pluggy0。13。1rootdir:C:UsersyuruoDesktopmpplugins:allurepytest2。8。11,forked1。3。0,rerunfailures9。1。1,timeout1。4。2,xdist2。2。1collected2itemstesta。yaml123456。123456。2passedin0。02s
利用pytest创建数据驱动测试框架就介绍到这里啦,希望能给大家带来一定的帮助。大家有什么不懂的地方或者有疑惑也可以留言讨论哈,让我们共同进步呦!
重点:学习资料学习当然离不开资料,这里当然也给你们准备了600G的学习资料
需要的私我关键字【000】免费获取哦注意关键字是:000
项目实战
app项目,银行项目,医药项目,电商,金融
大型电商项目
全套软件测试自动化测试教学视频
300G教程资料下载【视频教程PPT项目源码】
全套软件测试自动化测试大厂面经
python自动化测试全套模板性能测试
听说关注我并三连的铁汁都已经升职加薪暴富了哦!!!!
医生让我尝试使用产钳助产,我担心对宝宝有伤害,非常的抗拒编者按:分娩故事来自于【cr。heyjudyy】分享的我的剖腹产日记发力过程中宝宝胎心下降到了一个非常危险的数值,医生都围过来了,我又疲惫又害怕,医生建议我尝试产钳助产,我怕对……
长期吃猪油渣,对血管到底是受害还是受益医生说出答案随着生活水平的不断提高,猪油渣也已经淡出了很多的家庭,主要是因为现如今越来越多的人开始注重养生,认为长期吃猪油或者是长期吃猪油渣的话,会容易增加血管病的发生风险。那么长期……
白客的十年演员梦,拼尽全力,也终究入不了影视圈主流2013年,一部搞笑网剧《万万没想到》横空出世,创造了诸多奇迹,也捧红了诸多好演员。其中剧里饰演王大锤的白客更是一飞冲天,靠着一副面瘫脸红遍全网。然而随着万合天宜的……
月薪3000元,如何买保险?月薪3000元的话,可以先配置基础保障。具体如下:百万医疗险成人意外险,一年保费500元左右。一、百万医疗险和医保搭配使用,可以报销生病住院的医疗费用。保障生……
你的肝还好吗?喝酒真的可以喝到肝硬化的程度吗?春天到了好多朋友都在讨论怎么样保肝养肝,肝属木,所以春天养肝更加事半功倍。我们正常的肝脏,它的表面是光滑颜色红润,体积适中。而有的人肝脏,表面是粗糙的,颜色是暗淡发黄的,体积是……
能力?脾气?曾凡博被网友批评直接破防回怼,这种心态对他没好处关心中国篮球的朋友估计最近都听说了曾凡博这位小球员。19岁,身高211cm,从小在美国读高中和接受篮球训练;去年打上发展联盟,场均3。8分;今年参加NBA选秀落选。曾凡博……
王者荣耀天游正在毁掉限定标签,突袭式返场,只为氪金大家好,我是船长!在6月29日上午,《王者荣耀》进行了一次时长达一个小时的不停机更新维护,在这次的更新中,官方并没有对英雄、装备进行调整,而是上线了包含皮肤返场在内的大量……
孩子跟奶奶亲还是妈妈亲?错过了几个关键期,妈妈很难弥补回来韩国畅销小说《坡道上的家》的同名韩剧中,有这么一段情节:妈妈因为工作原因,将女儿暂时交给婆婆照顾几天。一周后,妈妈去接女儿回家,孩子却怎么也不愿意走了,说什么也要和奶奶待……
小米憋大招,5月份主场小米12ultra被爆料大家都知道,小米有一款数字型号的旗舰机还未发布,至今也未预热小米12ultra。小米12ultra作为小米的数字系列的王牌,拥有旗舰机最高的配置,不论性能、拍照、充电、功能等,……
莱昂纳德复出只差一步完整快船成附加赛巨头大家好!我是阜阳小麻雀,点击右上方关注,每天和你分享NBA最新比赛消息。北京时间3月25日,莱昂纳德因为膝盖伤病,本赛季至今还没有复出,不过近日有关他的康复进程,进行得格……
你若善良,百花盛开善良是做人的基本准则,你若善良,百花盛开,你若善良,天地有爱。人之初,性本善,性相近,习相远。苟不教,性乃迁,教之道,贵以专。上小学的时候,我们就学习三字经,耳濡目……
心若清净,独处也欢昨日三千繁华,都不过是梦一场,红颜易老,光阴似箭,你还记得那张纯真的笑脸吗?时间,渐渐带走了年少轻狂,也慢慢沉淀了冷暖自知。世事沧桑,往事历历在目,慢慢懂得,有些苦痛,不必讲出……