Pytest-常用装饰器
>fixture
fixture实现前置操作
[申明]
- 不带参数 @pytest.fixture
- 带参数 @pytest.fixture(scope="function", params=None, autouse=False, ids=None, name=None)
@pytest.fixture()
def login():
print('登录')
@pytest.fixture(autouse=True)
def get_info():
print('获取信息')
[调用方式]
- 做为参数传入
- 测试用例加上装饰 @pytest.mark.usefixtures(fixture_name)
@pytest.mark.usefixtures('get_info')
def test_demo3():
print('get info')
def test_demo1(self,login):
print('get user name ')
[参数说明]
scope:
- function(默认)--每个函数前运行
- class--class 前运行一次
- module--整个.py文件运行一次
- package--整个package下运行一次
- session--整个会话过程运行一次
@pytest.fixture(scope='module')
def login():
print('登录')
def test_demo3(login):
print('get info')
class Test_Demo():
def test_demo3(self, login):
print('get user sex ')
def test_demo1(self, login):
print('get user name ')
autouse:默认:False,需要用例手动调用该fixture;如果是True,所有作用域内的测试用例无需显示调用都会自动调用该fixture
@pytest.fixture(autouse=True)
def login():
print('登录')
def test_demo3():
print('get info')
class Test_Demo():
def test_demo3(self):
print('get user sex ')
def test_demo1(self):
print('get user name ')
name:默认:装饰器的名称,同一模块的fixture相互调用建议写个不同的name
多fixture:
#使用装饰器调用时,底部先执行
@pytest.mark.usefixtures('login')
@pytest.mark.usefixtures('get_info')
def test_demo3():
print('get info')
#使用参数调用时,前面的先执行
class Test_Demo():
def test_demo4(self,login,get_info):
print('get user sex ')
fixture 带参
1.调用时只可用参数调用
2.申明时参数带request,获取参数为request.param
3.传参装饰器需带参indirect=True,标识参数当函数执行。否则申明的fixture不会执行
单参
sex = ['g', 'b']
@pytest.fixture()
def login(request):
name = request.param
print('login para is {}'.format(name))
@pytest.mark.parametrize('login',sex,indirect=True)
def test_demo3(login):
print('get info')
多参--数据为字典格式
para2 = [
{'name':name[1],'tel':tel[1]},
{'name':name[2],'tel':tel[2]}
]
@pytest.fixture()
def login(request):
name = request.param
print('login name is {} ans tel is {}'.format(name['name'],name['tel']))
@pytest.mark.parametrize('login',para2,indirect=True)
def test_demo3(login):
print('get info')
多个fixture,一个传参装饰器:数据按传参顺序分发到各个fixture中
para2 = [
[name[1],tel[1]],
[name[2],tel[2]]
]
@pytest.fixture()
def name(request):
name = request.param
print('login name is {} '.format(name))
@pytest.fixture()
def sex(request):
sex = request.param
print('login sex is {} '.format(sex))
@pytest.mark.parametrize('name,sex',para2,indirect=True)
def test_demo3(name,sex):
print('get info')
多个fixture,多个装饰器--执行用例为笛卡尔积
[备注]数据名与函数名不要一致,容易报错
sex_data = ['g', 'b']
name_data = ['april', 'kka']
@pytest.fixture()
def name(request):
name = request.param
print('login name is {} '.format(name))
@pytest.fixture()
def sex(request):
sex = request.param
print('login sex is {} '.format(sex))
@pytest.mark.parametrize('name', name_data, indirect=True)
@pytest.mark.parametrize('sex', sex_data, indirect=True)
def test_demo5(name, sex):
print('get info')
fixture 可返回数据
@pytest.fixture()
def name(request):
name = request.param
return name
@pytest.mark.parametrize('name', name_data, indirect=True)
def test_demo5(name):
print('get name is {}'.format(name))
fixture实现后置操作
-
yield关键字
1.1 fixture申明的函数,添加yield关键字,yield之前得部分为前置,之后的部分为后置
1.2 若yield之前得部分抛异常,则后置也不执行
1.3 若用例抛异常,后置照常执行
1.4 yield 可返回前置操作返回的数据
@pytest.fixture()
def demo_fixture():
print("\n这个fixture在每个case前执行一次")
yield
print("\n在每个case完成后执行的teardown")
def test_01(demo_fixture):
print("\n===执行了case: test_01===")
-
addfinalizer
1.注册作为终结器使用的函数
2.request.addfinalizer(function_finalizer)
@pytest.fixture(scope="module")
def test_addfinalizer(request):
# 前置操作setup
print("==再次打开浏览器==")
test = "test_addfinalizer"
def fin():
# 后置操作teardown
print("==再次关闭浏览器==")
request.addfinalizer(fin)
return test
def test_anthor(test_addfinalizer):
print("==最新用例==", test_addfinalizer)
-
addfinalizer可以注册多个终结函数。即可执行多个不同后置操作。执行顺序,与注册的顺序相反
-
当setUp的代码执行错误,addfinalizer依旧会执行
fixture调用范围
同变量的使用,定义在类中的fixture,只有类中test可调用;定义在module中的fixture,module中test皆可调用.
fixture调用fxiture,则无范围限制。皆可调用.
@pytest.fixture
def order():
return []
@pytest.fixture
def outer(order, inner):
order.append("outer")
class TestOne:
@pytest.fixture
def inner(self, order):
order.append("one")
def test_order(self, order, outer):
assert order == ["one", "outer"]
conftest.py
全局fixture,无需引用,直接调用
Factories as fixtures
fixture传数据
@pytest.fixture
def make_customer_record():
def _make_customer_record(name):
return {"name": name, "orders": []}
return _make_customer_record
def test_customer_records(make_customer_record):
customer_1 = make_customer_record("Lisa")
customer_2 = make_customer_record("Mike")
customer_3 = make_customer_record("Meredith")
customer = [customer_1,customer_2,customer_3]
print('data is {}'.format(customer))
>Mark
1.注册
1.1 在pytest.ini文件中注册
[pytest]
markers =
slow: marks tests as slow (deselect with '-m "not slow"')
serial
1.2 在pyproject.toml文件中注册
[tool.pytest.ini_options]
markers = [
"slow: marks tests as slow (deselect with '-m \"not slow\"')",
"serial",
]
1.3 hook函数中注册
def pytest_configure(config):
config.addinivalue_line(
"markers", "env(name): mark test to run only on named environment"
)
2.使用
2.1使用前标记 @pytest.mark.name_of_the_mark
2.2 命令行 -m name_of_the_mark
2.3 使用非系统默认未注册的mark会报错