fixture的参数化

1|0背景


在需要每次都要进程一组设备测试的时候,需要用到fixtures参数化,比如需要对夜神和Honor 5C进行APP自动化测试,这时候参数化就可以起到很好的用途

这个两台设备实际应用中代码和报告:

params=["Honor_5C", "YeShen"] #登录:无toast弹框,不重置 @pytest.fixture(params=params) def login_common_driver(request): driver = BaseDriver().base_driver(device=request.param) is_welcome(driver) yield driver driver.close_app() driver.quit()

2|0参数化用法


2|1使用params 


request是pytest中内建的fixture之一,代表fixture的调用状态,request.param作为返回值供测试使用。比如下面的例子,简单判断下拿到的request.param值有没有在原来的参数列表中。实际上就相当于遍历了一遍参数列表(参数化变量actual_url可以是列表或元组)们可以看到测试方法被调用了两次

#test_fixture_param.py import pytest actual_url = ["www.baidu.com", "www.google.com"] @pytest.fixture(params=actual_url) def back_actual_url(request): return request.param def test_url(back_actual_url): assert back_actual_url in actual_url

2|2使用params + ids


如果没有指定ids,就是上面那个运行结果,额可以看到测试id拿的是参数列表中的元素。如果指定了ids,这个测试id就变成了了指定的值

#test_fixture_param.py import pytest actual_url = ["www.baidu.com", "www.google.com"] @pytest.fixture(params=actual_url, ids=["test001", "test002"]) def back_actual_url(request): return request.param def test_url(back_actual_url): assert back_actual_url in actual_url

ids也可以是一个函数,比如我们根据条件判断,如果默认id为"www.baidu.com",则通过idfunc()函数将"www.baidu.com"转化为"baidu",ids=idfunc用来接收转化后的值,然后指定id后,按照新的id值作为测试id

#test_fixture_param.py import pytest actual_url = ["www.baidu.com", "www.google.com"] def idfunc(fixture_value): if fixture_value == "www.baidu.com": return "baidu" else: return None @pytest.fixture(params=actual_url, ids=idfunc) def back_actual_url(request): return request.param def test_url(back_actual_url): assert back_actual_url in actual_url

3|0参数化之笛卡尔乘积


如果有下面一种场景,即同一个测试方法同时调用两个fixture,而这两个fixture又各自有两个参数,那么总共有要执行多少次用例?执行结果又如何?

#test_fixture_param.py import pytest actual_url = ["www.baidu.com", "www.google.com"] expect_url = ["www.baidu.com", "www.google.com"] @pytest.fixture(params=actual_url) def back_actual_url(request): return request.param @pytest.fixture(params=expect_url) def back_expect_url(request): return request.param def test_url(back_actual_url, back_expect_url): assert back_actual_url == back_expect_url

答案是4次,执行结果是两个PASS,两个Fail,这就是笛卡尔乘积:A = (0, 1),B = (0, 1), A X B = { (0, 0), (0, 1) (1, 0), (1, 1) },只有 0 = 0, 1 = 1,其他两种不相等,所以Fail

4|0fixture实例引起的测试自动分组


一个参数中的元素可以看做是一个fixture实例,有两个参数可以看做是调用了两次fixture实例。正如最开始提到的多个设备执行测试,有设备列表[夜神,Honor],有其他参数[1, 2],那么在执行必定是夜神-1,夜神-2,Honor-1,荣耀-2。举个更复杂的官方的例子:

#test_module.py
import
pytest @pytest.fixture(scope="module", params=["mod1", "mod2"]) def modarg(request): param = request.param print(" SETUP modarg", param) yield param print(" TEARDOWN modarg", param) @pytest.fixture(scope="function", params=[1, 2]) def otherarg(request): param = request.param print(" SETUP otherarg", param) yield param print(" TEARDOWN otherarg", param) def test_0(otherarg): print(" RUN test0 with otherarg", otherarg) def test_1(modarg): print(" RUN test1 with modarg", modarg) def test_2(otherarg, modarg): print(" RUN test2 with otherarg {} and modarg {}".format(otherarg, modarg))


=========================== test session starts ============================ platform linux -- Python 3.x.y, pytest-5.x.y, py-1.x.y, pluggy-0.x.y -- $PYTHON_PREFIX/bin/python cachedir: $PYTHON_PREFIX/.pytest_cache rootdir: $REGENDOC_TMPDIR collecting ... collected 8 items test_module.py::test_0[1] SETUP otherarg 1 RUN test0 with otherarg 1 PASSED TEARDOWN otherarg 1 test_module.py::test_0[2] SETUP otherarg 2 RUN test0 with otherarg 2 PASSED TEARDOWN otherarg 2 test_module.py::test_1[mod1] SETUP modarg mod1 RUN test1 with modarg mod1 PASSED test_module.py::test_2[mod1-1] SETUP otherarg 1 RUN test2 with otherarg 1 and modarg mod1 PASSED TEARDOWN otherarg 1 test_module.py::test_2[mod1-2] SETUP otherarg 2 RUN test2 with otherarg 2 and modarg mod1 PASSED TEARDOWN otherarg 2 test_module.py::test_1[mod2] TEARDOWN modarg mod1 SETUP modarg mod2 RUN test1 with modarg mod2 PASSED test_module.py::test_2[mod2-1] SETUP otherarg 1 RUN test2 with otherarg 1 and modarg mod2 PASSED TEARDOWN otherarg 1 test_module.py::test_2[mod2-2] SETUP otherarg 2 RUN test2 with otherarg 2 and modarg mod2 PASSED TEARDOWN otherarg 2 TEARDOWN modarg mod2 ============================ 8 passed in 0.12s =============================

看到这个结果是不是很疑惑

画了一个不太准确的图,简单说明下,为什么是这种执行顺序?首先pytest是按照test_0,test_1,test_2的顺序执行的

想象fixture实例在使用时就相当于占用了一个资源,当test_0执行时,资源先被[1, 2]中的1占用,然后虽然test_3也有用到[1, 2],但没有test_1还没有开始,是不能进入test_3的,所以资源传递给了[1, 2]中的2,同理2执行结束后,就开始了test_1,所以能把资源传递给mod1,当mod1在test_1中执行完后,发现test_2要用到它,于是继续给test_2使用,test_2使用完后,mod1将资源传递给了mod2,这时候mod2交给test_1先使用,最后传递给test_2使用

 

 

 


__EOF__

本文作者cnhkzyy
本文链接https://www.cnblogs.com/my_captain/p/12727176.html
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角推荐一下。您的鼓励是博主的最大动力!
posted @   cnhkzyy  阅读(1020)  评论(0编辑  收藏  举报
编辑推荐:
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
阅读排行:
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· 单线程的Redis速度为什么快?
点击右上角即可分享
微信分享提示