前言
上一篇带大家初步了解Pytest的核心知识点fixture,这一篇我们将继续对fixture进行介绍,我们会对fixture的调用方式进行一些补充,另外我们会介绍Pytest是如何进行参数化的。
fixture 的调用
fixture 调用方式之autouse-true
如果所有的用例都需要执行的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的函数名作为测试用例函数的一个参数,实际返回的是fixture的返回值,并不是函数本身 示例如下:
import pytest
@pytest.fixture()
def func():
obj = {"a": 1, "b": 2, "c": 3}
return obj
def 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_01
a 1
b 2
c 3
.in test_02
.in test_03
<class 'dict'>
.
在测试用例test_01
和测试用例test_03
中,func并不是指func这个函数,而是是func这个函数的返回值,这一点需要格外注意.
pytest 的参数化
在实际工作中,测试用例可能需要支持多种场景,我们可以把和场景强相关的部分抽象成参数,通过对参数的赋值来驱动用例的执行。
@pytest.mark.parametrize 标记
源码中的定义
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
本文分享自微信公众号 - 软件测试架构师俱乐部(gh_03227f9a322f)。
如有侵权,请联系 support@oschina.cn 删除。
本文参与“OSC源创计划”,欢迎正在阅读的你也加入,一起分享。