2024年浅谈基于Pytest框架的自动化测试开发实践_pytest自动化工程,2024年最新一文带你搞懂软件测试多线程Handler

   日期:2024-12-26    作者:yindufu1 浏览:64    移动:http://w.yusign.com/mobile/quote/6544.html

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化的资料的朋友,可以戳这里获取

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导,让我们一起学习成长

测试脚本中定义了一个读取测试数据的函数get_test_data,通过这个函数从测试数据文件test_in_theaters.yaml中读取到了测试用例名称case,请求对象http和预期结果expected。这三部分分别是一个列表,通过zip将他们压缩到一起。

测试方法test_in_theaters并没有太大变化,只是发送请求所使用的测试数据不是写死的,而是来自于测试数据文件了。

通常情况下,读取测试数据的函数不会定义在测试用例文件中,而是会放到utils包中,比如放到utils/commonlib.py中。至此,整个项目的目录结构应该是如下所示

 

这样,我们修改测试脚本,就修改test_in_theaters.py,变更测试数据,就修改test_in_theaters.yaml。但是目前看,感觉好像并没有真正看到测试数据和脚本分离的厉害之处,或者更加有价值的地方,那么我们接着往下看。

06 — 参数化

上面我们将测试数据和测试脚本相分离,如果要为测试用例添加更多的测试数据,往tests数组中添加更多的同样格式的测试数据即可。这个过程叫作参数化。

参数化的意思是对同一个接口,使用多种不同的输入对其进行测试,以验证是否每一组输入参数都能得到预期结果。Pytest提供了pytest.mark.paramtrize这种方式来进行参数化,我们先看下官方网站提供的介绍pytest.mark.paramtrize用法的例子

 

执行上面的脚本将会得到下面的输出,测试方法test_timedistance_v0被执行了两遍,第一遍执行用的测试数据是testdata列表中的第一个元组,第二遍执行时用的测试数据是testdata列表中的第二个元组。这就是参数化的效果,同一个脚本可以使用不同的输入参数执行测试。

 

照猫画虎,对我们自己的测试项目中的测试脚本进行如下修改。

 

在测试方法上面添加了一个装饰器@pytest.mark.parametrize,装饰器会自动对list(list_params)解包并赋值给装饰器的第一参数。装饰器的第一个参数中逗号分隔的变量可以作为测试方法的参数,在测试方法内就可以直接获取这些变量的值,利用这些值发起请求和进行断言。装饰器还有一个参数叫ids,这个值作为测试用例的名称将打印到测试结果中。

在执行修改后的测试脚本前,我们在测试数据文件再增加一组测试数据,现在测试数据文件中,包含了两组测试数据

 

现在我们执行一下测试脚本,看看效果

 

从结果看,Pytest收集到了2个items,测试脚本执行了两遍,第一遍执行用第一组测试数据,结果是失败(F),第二遍执行用第二组测试数据,结果是通过(.)。执行完成后的summary info部分,看到了一些Unicode编码,这里其实是ids的内容,因为是中文,所以默认这里显示Unicode编码。为了显示中文,需要在测试项目的根目录下创建一个Pytest的配置文件pytest.ini,在其中添加如下代码

 

再次执行测试脚本,在测试结果的summary_info部分,则会显示正确中文内容了。

 

按照这种参数化的方法,如果想修改或者添加测试数据,只需要修改测试数据文件即可。

现在,自动化测试项目的目录结构应该是如下这样

 

07 — 测试配置管理
06小节的自动化测试代码中,host是写在测试脚本中的,这种硬编码方式显然是不合适的。这个host在不同的测试脚本都会用到,应该放到一个公共的地方来维护。如果需要对其进行修改,那么只需要修改一个地方就可以了。根据我的实践经验,将其放到config文件夹中,是比较好的。

除了host外,其他与测试环境相关的配置信息也可以放到config文件夹中,比如数据库信息、kafka连接信息等,以及与测试环境相关的基础测试数据,比如测试账号。很多时候,我们会有不同的测试环境,比如dev环境、test环境、stg环境、prod环境等。我们可以在config文件夹下面创建子目录来区分不同的测试环境。因此config文件夹,应该是类似这样的结构

 

在config.yaml中存放不同环境的配置信息,以前面的例子为例,应该是这样

 

将测试配置信息从脚本中拆分出来,就需要有一种机制将其读取到,才能在测试脚本中使用。Pytest提供了fixture机制,通过它可以在测试执行前执行一些操作,在这里我们利用fixture提前读取到配置信息。我们先对官方文档上的例子稍加修改,来介绍fixture的使用。请看下面的代码

 

这段代码中,smtp_connection被装饰器@pytest.fixture装饰,表明它是一个fixture函数。这个函数的功能是连接163邮箱服务器,返回一个连接对象。当test_ehlo的最后一次测试执行完成后,执行print(“teardown smtp”)和connection.close()断开smtp连接。

fixture函数名可以作为测试方法test_ehlo的参数,在测试方法内部,使用fixture函数名这个变量,就相当于是在使用fixture函数的返回值。

回到我们读取测试配置信息的需求上,在自动化测试项目tests/目录中创建一个文件conftest.py,定义一个fixture函数env

 

conftest.py文件是一个plugin文件,里面可以实现Pytest提供的Hook函数或者自定义的fixture函数,这些函数只在conftest.py所在目录及其子目录中生效。scope="session"表示这个fixture函数的作用域是session级别的,在整个测试活动中开始前执行,并且只会被执行一次。除了session级别的fixture函数,还有function级别、class级别等。

env函数中有一个参数request,其实request也是一个fixture函数。在这里用到了它的request.config.rootdir属性,这个属性表示的是pytest.ini这个配置文件所在的目录,因为我们的测试项目中pytest.ini处于项目的根目录,所以config_path的完整路径就是

/Users/chunming.liu/learn/api_pytest/config/test/config.yaml

将env作为参数传入测试方法test_in_theaters,将测试方法内的host改为env[“host”][“douban”]

 

这样就达到了测试配置文件与测试脚本相互分离的效果,如果需要修改host,只需要修改配置文件即可,测试脚本文件就不用修改了。修改完成后执行测试的方法不变。

上面的env函数实现中,有点点小缺憾,就是读取的配置文件是固定的,读取的都是test环境的配置信息,我们希望在执行测试时,通过命令行选项,可指定读取哪个环境的配置,以便在不同的测试环境下开展测试。Pytest提供了一个叫作pytest_addoption的Hook函数,可以接受命令行选项的参数,写法如下

 

pytest_addoption的含义是,接收命令行选项–env选项的值,存到environment变量中,如果不指定命令行选项,environment变量默认值是test。将上面代码也放入conftest.py中,并修改env函数,将os.path.join中的"test"替换为request.config.getoption(“environment”),这样就可以通过命令行选项来控制读取的配置文件了。比如执行test环境的测试,可以指定–env test

 

如果不想每次都在命令行上指定–env,还可以将其放入pyest.ini中

 

命令行上的参数会覆盖pyest.ini里面的参数。

2024年浅谈基于Pytest框架的自动化测试开发实践_pytest自动化工程,2024年最新一文带你搞懂软件测试多线程Handler

08 — 测试的准备与收尾
很多时候,我们需要在测试用例执行前做数据库连接的准备,做测试数据的准备,测试执行后断开数据库连接,清理测试脏数据这些工作。通过07小节大家对于通过env这个fixture函数,如何在测试开始前的开展准备工作有所了解,本小节将介绍更多内容。

@pytest.fixture函数的scope可能的取值有function,class,module,package 或 session。他们的具体含义如下

function,表示fixture函数在测试方法执行前和执行后执行一次。
class,表示fixture函数在测试类执行前和执行后执行一次。
module,表示fixture函数在测试脚本执行前和执行后执行一次。
package,表示fixture函数在测试包(文件夹)中第一个测试用例执行前和最后一个测试用例执行后执行一次。
session,表示所有测试的最开始和测试结束后执行一次。
通常,数据库连接和断开、测试配置文件的读取等工作,是需要放到session级别的fixture函数中,因为这些操作针对整个测试活动只需要做一次。而针对测试数据的准备,通常是function级别或者class级别的,因为测试数据针对不同的测试方法或者测试类往往都不相同。

在TestInTheaters测试类中,模拟一个准备和清理测试数据的fixture函数preparation,scope设置为function

 

在测试方法中,将preparation作为参数,通过下面的命令执行测试

 

通过输出可以看到在每一条测试用例执行前后,各执行了一次“在数据库中准备测试数据”和“清理测试数据”。如果scope的值改为class,执行测试用例的输出信息将是下面这样

tests/test_in_theaters.py 在数据库中准备测试数据
F.清理测试数据
在测试类执行前后各执行一次“在数据库中准备测试数据”和“清理测试数据”。

09 — 标记与分组

通过pytest.mark可以给测试用例打上标记,常见的应用场景是:针对某些还未实现的功能,将测试用例主动跳过不执行。或者在某些条件下,测试用例跳过不执行。还有可以主动将测试用例标记为失败等等。针对三个场景,pytest提供了内置的标签,我们通过具体代码来看一下

 

下面来运行这个测试

 

从结果中可以看到,第一条测试用例skipped了,第二条测试用例passed了,第三条和第四条测试用例xfailed了。

除了内置的标签,还可以自定义标签并加到测试方法上

 

这样就可以通过-m过滤或者反过滤,比如只执行被标记为slow的测试用例

 

对于自定义标签,为了避免出现PytestUnknownMarkWarning,最好在pytest.ini中注册一下

 

10 — 并发执行
如果自动化测试用例数量成千上万,那么并发执行它们是个很好的主意,可以加快整体测试用例的执行时间。

pyest有一个插件pytest-xdist可以做到并发执行,安装之后,执行测试用例通过执行-n参数可以指定并发度,通过auto参数自动匹配CPU数量作为并发度。并发执行本文的所有测试用例

 

可以非常直观的感受到,并发执行比顺序执行快得多。但是并发执行需要注意的是,不同的测试用例之间不要有测试数据的相互干扰,最好不同的测试用例使用不同的测试数据。

这里提一下,pytest生态中,有很多第三方插件很好用,更多的插件可以在这里https://pypi.org/search/?q=pytest-查看和搜索,当然我们也可以开发自己的插件。

11 — 测试报告
Pytest可以方便的生成测试报告,通过指定–junitxml参数可以生成XML格式的测试报告,junitxml是一种非常通用的标准的测试报告格式,可以用来与持续集成工具等很多工具集成

 

现在应用更加广泛的测试报告是Allure,可以方便的与Pytest集成,大家可以参考我的另外一篇公众号文章《用Pytest+Allure生成漂亮的HTML图形化测试报告》。

12 — 总结
本文章以实际项目出发,介绍了如何编写测试用例、如何参数化、如何进行测试配置管理、如何进行测试的准备和清理,如何进行并发测试并生成报告。根据本文的介绍,你能够逐步搭建起一套完整的测试项目。

本文并没有对Pytest的细节和比较高阶的内容做充分介绍,以后再进行专题介绍,这篇文章主要目的是让大家能够将Pytest用起来。更高阶的内容,后续文章还将继续对其进行介绍。至此,我们的自动化测试项目完整目录结构如下

 

$ tree
.

[外链图片转存中…(img-JUWhIeVV-1715165286653)]
[外链图片转存中…(img-i6FZpA2M-1715165286654)]

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化的资料的朋友,可以戳这里获取

本文地址:http://w.yusign.com/quote/6544.html    述古往 http://w.yusign.com/static/ , 查看更多

特别提示:本信息由相关用户自行提供,真实性未证实,仅供参考。请谨慎采用,风险自负。


举报收藏 0评论 0
0相关评论
相关行情
推荐行情
点击排行
{
网站首页  |  关于我们  |  联系方式  |  用户协议  |  隐私政策  |  版权声明  |  网站地图  |  排名推广  |  广告服务  |  积分换礼  |  网站留言  |  RSS订阅  |  违规举报  |  鄂ICP备2020018471号