上一篇带大家初步了解Pytest的核心知识点fixture,这一篇我们将继续对fixture进行介绍,我们会对fixture的调用方式进行一些补充,另外我们会介绍Pytest是如何进行参数化的。
如果所有的用例都需要执行的fixture,就没有必要再所有用例中通过传参的方式或者标记的方式,pytest的fixture提供了一种更为简洁的用例,即在定义fixture的时候,将参数autouse设置为True时,则在执行用例的时候自动去加载,无需显示调用
import pytest@pytest.fixture(scope="function",autouse=True)def func3(): print("in fixture func3 before testcase......") yield print("in fixture func3 after testcase......")def test_01(): print("in test_01")def test_02(): print("in test_02")def test_03(): print("in test_03")
我们可以看到运行结果,每一个函数都会调用func3
pytest_dmeo.py in fixture func3 before testcase......in test_01.in fixture func3 after testcase......in fixture func3 before testcase......in test_02.in fixture func3 after testcase......in fixture func3 before testcase......in test_0.in fixture func3 after testcase......
fixture 的另一个功能:fixture的函数名作为测试用例函数的一个参数,实际返回的是fixture的返回值,并不是函数本身 示例如下:
import pytest@pytest.fixture()def func(): obj = {"a": 1, "b": 2, "c": 3} return objdef test_01(func): print("\nin test_01") for key, value in func.items(): print(key, value)def test_02(): print("in test_02")def test_03(func): print("in test_03") print(type(func))------------------------------in test_01a 1b 2c 3.in test_02.in test_03<class 'dict'>.
在测试用例test_01
和测试用例test_03
中,func并不是指func这个函数,而是是func这个函数的返回值,这一点需要格外注意.
在实际工作中,测试用例可能需要支持多种场景,我们可以把和场景强相关的部分抽象成参数,通过对参数的赋值来驱动用例的执行。
源码中的定义
def parametrize(self, argnames, argvalues, indirect=False, ids=None, scope=None):
1.argnames:一个用逗号分隔的字符串,或者一个列表/元组,表明指定的参数名;对argnames,有如下限制:
•定义了,就一定要用到
@pytest.mark.parametrize('input, expected', [(1, 2)])def test_sample(): assert 1 == 1
么有用到 定义的参数,运行会报错
================================================================================== ERRORS ==================================================================================_____________________________________________________________________ ERROR collecting pytest_dmeo.py ______________________________________________________________________In test_sample: function uses no argument 'input'========================================================================= short test summary info ==========================================================================ERROR pytest_dmeo.py!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! Interrupted: 1 error during collection !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!============================================================================= 1 error in 0.14s =============================================================================
•修饰函数中,不能有默认值
def test_sample(input, expected=0): assert input + 1 == 1
定义参数有默认值,运行也会报错
================================================================================== ERRORS ==================================================================================_____________________________________________________________________ ERROR collecting pytest_dmeo.py ______________________________________________________________________In test_sample: function already takes an argument 'expected' with a default value========================================================================= short test summary info ==========================================================================ERROR pytest_dmeo.py!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! Interrupted: 1 error during collection !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!============================================================================= 1 error in 0.15s =============================================================================
•会覆盖同名的fixture: 上面说过,fixture 可以传递值
@pytest.fixture()def expected(): return 1@pytest.mark.parametrize('input, expected', [(1, 2)])def test_sample(input, expected): assert input + 1 == expected
运行结果如下:
collected 1 item pytest_dmeo.py .
如果excepted 是 利用 fixture 传递过来的值,则会断言失败,但这边参数会覆盖同名的fixture。
1.argvalues: 一个可迭代对象,表明对argnames参数的值
•如果argnames包含多个参数,那么argvalues的迭代返回元素必须是可度量的,并且长度和argnames声明参数的个数相等,它可以是元组/列表/集合等,表明所有入参的实参:
@pytest.mark.parametrize('input, expected', [(1, 2), [2, 3], set([3, 4])])def test_sample(input, expected): assert input + 1 == expected
运行结果如下:
...3 passed in 0.01s
可以看到,运行了3次!!! 我们不建议用set ,因为他有去重性
•如果argnames只包含一个参数,那么argvalues的迭代返回元素可以是具体的值
@pytest.mark.parametrize('input', [1, 2, 3])def test_sample(input): assert input + 1
1.多个标记组合 如果一个函数标记了多个@pytest.mark.parametrize标记
@pytest.mark.parametrize('test_input', [1, 2, 3])@pytest.mark.parametrize('test_output, expected', [(1, 2), (3, 4)])def test_multi(test_input, test_output, expected): print(test_input, test_output, expected)
运行结果如下:
1 1 2.2 1 2.3 1 2.1 3 4.2 3 4.3 3 4.6 passed in 0.03s