小门板儿

Menu

pytest:参数化的夹具和测试

pytest在多个级别上都可以做参数化: 1、pytest.fixture() 允许用户参数化夹具函数 2、@pytest.mark.parametrize 允许用户给测试方法或者类定义多组参数或者多个夹具 3、pytest_generate_tests允许用户定义自定义的参数格式或者扩展

一、@pytest.mark.parametrize: 参数化测试方法

内置的 pytest.mark.parametrize 修饰器允许测试参数的参数

@pytest.mark.parametrize("input,expected",[("1+3",5),('2+2',4)])
def test_a(input,expected):
   assert eval(input)==expected
执行测试:
============ FAILURES =============
____________ test_a[1+3-5] ____________
input = '1+3', expected = 5

   @pytest.mark.parametrize("input,expected",[("1+3",5),('2+2',4)])
   def test_a(input,expected):
>       assert eval(input)==expected
E       AssertionError: assert 4 == 5
E        +  where 4 = eval('1+3')

e\test_param2.py:6: AssertionError
============================ short test summary info =============================
FAILED e/test_param2.py::test_a[1+3-5] - AssertionError: assert 4 == 5
1 failed, 1 passed in 0.23s

注意:默认情况下pytest会使用unicode字符串转义所有的非unicode参数,因为非unicode会导致一些问题。如果你就是想在参数中使用unicode字符串,并且在输出窗口也希望看到unicode(非转义的),你可以在pytest.ini中使用这个选项:

[pytest] 

disable_test_id_escaping_and_forfeit_all_rights_to_community_support = True

在用例的设计中,只有一对输入/输出会产生失败。通常情况下,你可以在追踪信息中看到输入和输出值。 你也可以在类或者模块中使用 parametrize 标记,它们里面可以包含很多拥有参数组的测试。 我们也可以给参数化的一组参数中的某一个独立的测试添加标记,例如内置的标记 xfail:

@pytest.mark.parametrize("input,expected",[pytest.param("1+3",5,marks=pytest.mark.xfail),('2+2',4)])
def test_a(input,expected):
   assert eval(input)==expected
运行测试:
D:\pytest\learn01>pytest -s -q   e/test_param2.py
x.
1 passed, 1 xfailed in 0.08spython

如果给一个空的参数(parametrize),例如使用某个方法生成参数结果为空,这种情况pytest的行为使用 empty_parameter_set_mark 选项指定

将 parametrize 叠在一起,你会得到所有参数的组合

import pytest

@pytest.mark.parametrize("x", [0, 1])
@pytest.mark.parametrize("y", [2, 3])
def test_foo(x, y):
   print(x,y)
执行测试:
D:\pytest\learn01>pytest -s -q   e/test-param3.py
0 2
.1 2
.0 3
.1 3
.
4 passed in 0.30s

二、pytest_generate_tests

一些情况下,可能想要实现自己的参数化方案或为参数的确定或者夹具的scope确定提供动态改变的能力。这种情况,可以使用pytest_generate_tests钩子,它会在收集测试的时候调用。通过传入的metafunc对象,可以获取测试请求的上下文,最重要的是,可以调用metafunc.parameterize()来做参数化。

param metafunc:共有五个属性值
                    metafunc.fixturenames:参数化收集时的参数名称
                    metafunc.module:使用参数名称进行参数化的测试用例所在的模块d对象
                    metafunc.config:测试用例会话
                    metafunc.function:测试用例对象,即函数或方法对象
                    metafunc.cls: 测试用例所属的类的类对象

在 conftest.py 自定义参数化的钩子, 判断当测试用例传了 param 参数,就让它生成参数化的用例

def pytest_generate_tests(metafunc):
   if "param" in metafunc.fixturenames:
       metafunc.parametrize(
           "param",
           metafunc.module.test_data,
           ids=metafunc.module.names,
           scope="function"
      )
 #content of test_param.py
names=["test1","test2"]
test_data=[{
               "url": "http://www.baidu.com",
               "method": "GET",
               "headers":
                  {
                       "Content-Type": "application/json"
                  },

      },
      {
           "url": "http://www.qq.com",
           "method": "GET",
           "headers":
              {
                   "Content-Type": "application/json"
              },

      }]
def test_login(param):
   r = requests.session().request(**param)
   print(r.cookies)
执行测试:
D:\pytest\learn01>pytest -s -q   e/test-param3.py
<RequestsCookieJar[<Cookie BDORZ=27315 for .baidu.com/>]>
.<RequestsCookieJar[]>
.
2 passed in 0.47s

参考文档:https://www.cnblogs.com/yoyoketang/p/14106959.html

— 于 共写了2971个字
— 标签:

评论已关闭。