接口测试 - 从0不到1的心路历程 (二)
前段时间我发布了一篇有关自己做接口测试的实践经验,发出后受到了许多小搭档的关注,也收到了许多佬儿哥的指点,很是开心,TesterHome真是一个温暖的地方。在众多建议中,频率最高的就是"pytest+requests+allure"的组合了,随后我就学习了pytest和allure的相干知识,并且在项目中举行了实践。本次我就总结一下基于这个框架的阶段性结果,希望搭档们继承纠偏指点。书接上文 - 第三代测试框架
第三代测试框架是基于unittest+requests实现的,利用ddt库实现了数据驱动测试,利用excel管理测试数据,以及利用excel长期化接口相应的相干信息,具体细节感爱好的小搭档可以点击查看上篇文章:。依据这个模式写了30个接口的case,发现如下问题:
1.编写测试数据生成函数时,不光要写数据生成逻辑的代码,还要写将测试数据写入excel的代码,导致整个函数冗长,函数职能不单一。
2.利用excel生存接口相应的相干信息,每个接口单独占据一个sheet页,这种方式一旦接口数量过多,最终查阅起来并不方便 (首先打开 excel,然后查找目标sheet,然后再查找目标case)。
学习allure之后,发现allure可以记录接口的入参及接口相应等信息,基于此就可以完善解决上述问题,测试数据生成函数仅需要编写数据生成逻辑,无需再写处理excel相干代码。接口相应等信息直接利用 allure.attach() 方法就可以记录在陈诉中,以是也就不消再像版本三一样编写收集接口相应信息并写入到 excel 的函数了。先上两张excel陈诉和allure陈诉的效果对比图,然后再叙述第四版框架的堆砌过程。
https://i-blog.csdnimg.cn/blog_migrate/61d99ee39f47430a1d341d7771550d7d.png
https://i-blog.csdnimg.cn/blog_migrate/36ab07c79e51dc5952b33b32c06eb77a.png
初识pytest
我紧张是通过《pytest 测试实战》这本书学习pytest的,这是一本工具书,整书不厚,看完前四章就可以动手实战了,有爱好的搭档也可以看一下。pytest的优势在此就不过多赘述了,不过我以为还是很有必要了解一下pytest和unittest 的区别的,我在网上借了一张对比图,刚了解pytest的搭档可以参考下。
https://i-blog.csdnimg.cn/blog_migrate/5b52bc04c45b8e6488653bbe11fd1b3f.png
在pytest利用过程中,有三点优势是我切实感受到的:
1.pytest利用assert关键字来举行断言,相比unittest的断言就四个字:简便明白
https://i-blog.csdnimg.cn/blog_migrate/099826da4f9b07f989f3d6ed50579637.png
https://i-blog.csdnimg.cn/blog_migrate/8f2d863d14437c512e60dae401e2cb01.png
2.pytest提供的失败重跑插件"pytest-rerunfailures"。
例举一个利用场景:case1为新建商品,新建成功后生存商品 id,case2为编辑商品,需要利用case1生存的商品id。在运行测试脚本时,case2有一定概率会报错,提示被测系统中不存在此商品id,但事后手动执行case2发现并没有问题。究其缘故原由大概是case1的新建接口新建完商品后需要一定的时间举行数据落库等操作,但运行测试脚本时,case1和case2的衔接时间又很短,导致case2有一定概率会报错。在利用 unittest 框架时,对于这种场景,我一样寻常会在case2发送请求前强行休眠1秒:sleep(1) ,不过像这种蠢呆呆的代码我都会用遮羞布盖住,生怕别人瞥见。不过接触到"pytest-rerunfailures"插件后,再也不消担心这个问题了,只能用四个字形容:极其好用!
前提条件:pytest (>=5.3) 和 python >=3.6
安装:
[*] pip install pytest-rerunfailures
[*] pip show pytest-rerunfailures
利用:
[*] 命令行参数:--reruns n(重新运行次数)–reruns-delay m(等候运行秒数)
[*] 利用装饰器:/@pytest.mark.flaky(reruns=5, reruns_delay=2)
注意兼容性:
[*] 这个插件不可以和 class, module, package 级别的 fixture 装饰器一起利用;
[*] 这个插件与 pytest-xdist 的 --looponfail 标记不兼容;
[*] 这个插件与核心 --pdb 标记不兼容。
https://i-blog.csdnimg.cn/blog_migrate/7a929f074ab46f4a5aacef5ccb80e090.png
3.pytest 的参数化-@pytest.mark.parametrize(‘参数名’, list) 。
这个装饰器的利用很简朴,大致为:第一个参数是字符串,多个参数中间用逗号隔开;第二个参数是 list。我觉得比较有意思的一点是可以利用多个@pytest.mark.parametrize(‘参数名’, list) ,最终效果就是每一个参数化装饰器中可选值的笛卡尔积,在上篇文章的讨论区中,有小搭档就问过,参数组合的场景中,想做全面的笛卡尔积应该怎么做,喏,用@pytest.mark.parametrize(‘参数名’, list) 就可以解决你的问题了。让我们演示一下 (方法虽好,可不要过于迷恋,非必要我们还是要慎用笛卡尔积的,毕竟也要考虑用例冗余带来的效能问题):
https://i-blog.csdnimg.cn/blog_migrate/edfed3be21156992ad460be7483b86ef.png
初识allure
allure是一个机动的轻量级多语言测试陈诉工具。在利用 allure之前,需要安装"allure 命令行工具"和"allure-pytest"插件,需要注意的是,allure需要依靠jdk,我想it人电脑上jdk应该是标配吧,以是在此就不过多先容jdk的安装详情。
allure命令行工具安装步骤:
1.下载安装包,我选择的是"allure-2.20.1.zip",allure 安装包下载地点
2.解压缩
3.配置情况变量 path,我的是:D:\Gxy\allure-2.20.1\allure-2.20.1\bin
4.查抄是否配置成功,在 cmd 命令窗口输入: allure --version
https://i-blog.csdnimg.cn/blog_migrate/dc263736cfc8b158b1b71f956fd474ce.png
"allure-pytest"插件安装:
1.pip install allure-pytest
allure 运行命令:
1.pytest --alluredir ./report ./test_dir # 生成测试陈诉所需要的数据,数据在 report 目录里。
2.allure serve report # 会主动利用默认浏览器打开 allure 陈诉,默认是英文的,我们可以在页面左下角切换成中文显示。
3.如果我们想每次的陈诉不掺杂历史数据,那我们可以在运行测试命令背面加"--clean-alluredir"。如许最终的命令就是:
"pytest --alluredir ./report ./test_dir --clean-alluredir"
项目实践
首先先容一下我的项目目录,相比之前版本的测试框架,去除了TestRunner 文件夹 (用于生成测试陈诉),项目标根目录下多了"conftest.py"、"requirements.txt"和"result"文件,具体如下:
https://i-blog.csdnimg.cn/blog_migrate/ad0782a62e5288ce9e92c885ab6cffb2.png
在实践过程中,我有思考以下问题:
问题1:pytest怎么控制用例的执行顺序?
问题1的解答:
在unittest 框架中,默认按照ACSII码的顺序加载测试用例并执行,顺序为:09、AZ、a~z,测试目录、测试模块、测试类、测试方法/测试函数都按照这个规则来加载测试用例。
pytest 默认执行顺序:测试目录、测试模块,按照排序顺序执行。
pytest 也自界说执行顺序:需要安装 pytest-ordering 插件。
# 需要利用 @pytest.mark.run()@pytest.mark.run(order=2)def test_a(): print("test_a")@pytest.mark.run(order=1)def test_2(): print("test_2")
因为我这套测试脚本,用例间还是很考究运行顺序的,以是我就遵循pytest按照排序顺序执行的特点顺序编写测试脚本。起初我并没有给case举行编号,只是单单的按照排列顺序写,可在查看allure测试陈诉时,发现陈诉中case显示的顺序并不是按照脚本中case排列顺序展示的,并且我手动点击allure陈诉中排序规则后,还是没能按照脚本中case的顺序举行展示,这就令我很恼火,于是我还是按照unittest中根据名称排序的习惯,将全部case的标题都改了一遍,果然,allure陈诉中case的顺序被我成功拿捏住了。效果如下:
https://i-blog.csdnimg.cn/blog_migrate/70163f6eea95a889f0c3e99330238322.png
问题2:有接口数据依靠时,怎么判断依靠数据被成功赋值
场景形貌:还是以新增和编辑接口举例,首先我会在 config.py 文件中设置一个商品id,初始值为-1,然后新增接口的 case 断言通过后会重新赋值这个商品 id,最后编辑接口case运行前,需要先判断config.py 文件中的商品 id 是否被成功赋值,成功赋值则继承运行case后续代码,如果没有成功赋值则不运行 case2后续代码。
我在第三版测试框架中是如许做的:
https://i-blog.csdnimg.cn/blog_migrate/30fa7f4660b0ef3d469a388661533cc4.png
如果我在第四版中依然沿用这个思绪,那一旦依靠参数没有被成功赋值,则在 allure 陈诉中会显示本条 case 失败,可实在本条 case 并没有被运行,以是感觉被置为失败不确切。
def test_getGuideItem(self, case, expect, desc): if config.id_subjectId != -1: assert 1 == 2, '未获取到科室id,以是无法获取手术项目'
https://i-blog.csdnimg.cn/blog_migrate/b5529e700efe134cc36c44dad544603c.png
那我将 “assert 1 == 2” 改成"raise KeyError()"效果怎么样呢?
def test_getGuideItem(self, case, expect, desc): if config.id_subjectId != -1: raise KeyError('未获取到科室id,以是无法获取手术项目')
https://i-blog.csdnimg.cn/blog_migrate/183df23426205766625e1274a2ec6a69.png
在allure陈诉中显示故障好像也不太恰当,分析后实在这种情况应该属于case 入参没拿到,以是跳过本条用例,那天然而然的就想到了pytest跳过测试用例相干知识。pytest跳过测试用例大致分为方法外跳过 (@pytest.mark.skip()) 和方法内跳过 (pytest.skip()),分别演示:
# 利用方法外跳过@allure.story('获取手术项目列表')@pytest.mark.skipif(config.id_subjectId == -1, reason='未获取到科室id,以是无法获取手术项目')def test_getGuideItem(self, case, expect, desc): ....
经实践后发现,方法外跳过行不通,因为测试脚本运行时会先加载全部效例的装饰器,然后才会执行用例自己,而我们的依靠参数 (config.id_subjectId) 是在运行用例过程中举行赋值的,以是方法外跳过的装饰器读取的是原值,读不到变更后的值。
# 利用方法内跳过@allure.story('A1a3_获取手术项目列表')def test_A1a3_getGuideItem(self, keys, token): if config.id_subjectId == -1: pytest.skip(msg='未获取到科室id,以是无法获取手术项目') url = config.HOST_LAPI + 'getGuideItem' ......
经实践后发现,利用方法内调过可以达到期望效果。如果依靠参数没有被赋值,那么在 allure 陈诉中会显示此用例被跳过。这个结果就很符合现实情况了。
https://i-blog.csdnimg.cn/blog_migrate/38aa6c502feb7c2bb71406e70bf76508.png
项目总结
在第四版测试框架中,我一共写了101个接口,共计342条 case,这些是我从公司业务中梳理出来的紧张流程中涉及到的全部接口,因为团队中的接口文档并不是很完善,以是我紧张通过fiddler抓包工具收集涉及到的接口及其入参出参,工作量真心不小,但幸亏第四版的测试框架编写起case来相对简便,让我很快就完成了全部工作。为了更直观的体现第四版的简便,让我们来对比一下第四版和第三版编写相同 case 时需要的代码量 (一条case由case自己和造数函数两部门构成):
https://i-blog.csdnimg.cn/blog_migrate/0a4b5fb5f145a446c84de17ec3cdbeec.png
https://i-blog.csdnimg.cn/blog_migrate/6eba854b44dbe56a4afd914d2ad4b969.png
从代码量来看,实现相同的效果,岂论代码逻辑,就单单代码数量就约莫减少了三分之一,确实很不错!
从运行时间来看,整个脚本运行大概需要110秒左右的时间,如果这些核心流程人工点点点的话,业务纯熟如我的人也需要至少半个小时,从运行时间上也能很好的体现出接口测试确实是一把利器,值得测试人员为之投入。
第四版框架的实践总结就写到这里吧,固然磕磕绊绊的实现了,但自知其中绝对还有很大的优化空间,刚接触 pytest+allure不久,理论和实操经验都很是欠缺,就比如在刚接触pytest的时候,许多资料显示pytest的核心之一是 fixture、conftest等,而我却压根没用到这些,对其也是一知半解,显然我这pytest用的就很皮毛了 ,以是期望社区中的佬儿哥、佬儿姐们可以或许对发现的问题纠偏赐教,也希望和我一样刚接触pytest的搭档可以或许相互讨论一下自己的踩坑史。
一切并非顺风顺水
实在在第四版框架堆砌的过程中,踩坑无数,我将一些最令人头大的坑摆列一下,希望可以或许帮助一样在探索的搭档们。
踩坑 1.切换办公电脑后,项目标Python运行虚拟情况无法利用。
场景形貌:由于疫情缘故原由,一直居家办公,项目是在家里电脑 (电脑A) 创建的,创建时是用pycharm创建的虚拟情况。之后疫情稍微稳定,返回公司办公。我就用电脑A将项目上传到了git上,然后用公司的电脑 (电脑B) 克隆项目。最后利用电脑B运行项目发现Python运行情况无法利用。(现在知道问题是由于用电脑A上传git时,将项目根目录下的venv文件夹 (虚拟情况及项目依靠文件) 一同上传到了git 上,然后用电脑B克隆项目,由于项目在不同电脑上的路径不一样,导致电脑A的venv文件夹在电脑B无法正常利用)(但是当时并不知道),然后当时就只能在电脑B上重新创建虚拟情况,然后再重新安装项目依靠,下班时再用电脑B上传项目到git上,回家后用电脑A拉取项目,同样在重新创建虚拟情况,然后再重新安装项目依靠。反复几次后,实在受不了自己这种 stupid donkey的举动。决定先解决这个问题。
解决方案1:不利用虚拟情况,改用全局情况;但大概出现不同项目间依靠包版本冲突的问题,以是弃用方案1。
解决方案2:创建.gitignore文件,忽略venv文件;
经过一系列实践,发现方案2可行。最终项目中的.gitignore 文件内容如下:
https://i-blog.csdnimg.cn/blog_migrate/f9ee90d50a2997ccec1cbda03ae8daf3.png
但为了快捷的安装项目依靠,又学到了 requirements.txt 相干知识。具体如下:
在项目终端运行:pip freeze -> requirements.txt
这条语句可以将项目依靠信息生存为 txt 文档。
https://i-blog.csdnimg.cn/blog_migrate/8ff45a0cd139b33963402463fee07dcd.png
然后再在新的运行情况中运行命令:pip install -r requirements.txt
如许就可以快速的安装项目依靠了。
过程中又联想到另一个分支问题,为什么利用 pip freeze 而不是常见的 pip list?
随后我又利用 pip list -> list.txt 命令导出了 list 文件,两个文件对比如下:
https://i-blog.csdnimg.cn/blog_migrate/e5c647b72875cc6d461696f1beaa5cb2.png
发现pip list比pipfreeze多了"pip"和"setuptools"两个文件。
度娘之后得到如下结论:
"pip , wheel , setuptools等包,是自带的而无法 (un) install的。考虑到pip freeze的用途,以是这些包并没有显示。如果一定要用pip freeze来显示全部包,可以加上参数-all,即pip freeze -all"
踩坑2:项目路径中含有中文,导致在terminal运行语句:pytest --alluredir report test_dir 时报错 "pytest: error: unrecognized arguments: --alluredir"。
这个问题只有在我家里电脑上才会出现,在公司电脑上不会出现。
起初我以为是家里电脑Python的运行情况有问题,结果重新创建运行情况后,仍然存在此问题。
然后我又怀疑是家里pycharm有问题,然后我就将家里电脑的pycharm卸载,重新安装成和公司电脑一样版本的pycharm,运行后仍然存在问题。(现在想想有点搞笑,terminal报错,跟pycharm有什么关系呢 )
最后百度寻找答案,其中有一条结论说"虚拟情况地点不能有中文",然后我看一下自己项目标路径 (G:\耿晓野的口袋\PycharmProjects\pytest_requests_allure_v1),确实有中文,然后我就把项目路径更改成 (G:\gxyPocket\PycharmProjects\pytest_requests_allure_v1),由于项目路径变更,我不得不重新创建项目虚拟情况并且重新安装项目依靠,随后再次在 terminal 运行语句:pytest --alluredir report test_dir,成功了!
由此也解答了为什么办公室电脑运行就没问题,因为项目直接放在了办公室电脑上的 D 盘下。忽然想起上学时 Java 老师说路径中尽量不要有中文,不然会引发很奇怪的问题,喏,这回被我切实体会了一次。
知识点 3:在利用 pytest 过程中,用到了大量的装饰器,我就在想,函数上方摆列这么多装饰器有没有前后顺序要求?多个装饰器的执行顺序是怎样的?
百度及实践后得到以下结论:
装饰器函数的执行顺序是分为(被装饰函数)界说阶段和(被装饰函数)执行阶段的,装饰器函数在被装饰函数界说好后立刻执行;
在函数界说阶段:执行顺序是从最靠近函数的装饰器开始,自内而外的执行;
在函数执行阶段:执行顺序由外而内,一层层执行;
https://i-blog.csdnimg.cn/blog_migrate/9e389a16aa7eccee4df9bb52db88f6d8.png
本次实践过程中掉坑和爬坑过程就写这么多吧,如果你也有有趣的爬坑经验,也可以写在留言区,大家相互讨论下。
实在这次我不光重构了第四版测试框架,还买了个服务器,并且在服务器上搭建了jenkins,最终实现了jenkins每天定时利用git拉取代码,主动构建项目,并且把测试陈诉发送到我邮箱的效果。我打算也将这个过程总结输出一下,大概更多是每一步的操作步骤以及一些注意事项,应该会雷同于CI/CD创建分析书。如果感爱好的搭档可以继承关注一下~
资源分享【这份资料必须领取~】
下方这份完整的软件测试视频学习教程已经上传CSDN官方认证的二维码,朋友们如果需要可以自行免费领取 【包管100%免费】
https://i-blog.csdnimg.cn/blog_migrate/f8a70f533dd24755ee1d10330d60a7ab.png#pic_center
https://i-blog.csdnimg.cn/blog_migrate/f0c6b50605de96972785cd62818dbded.png#pic_center
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
页:
[1]