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会报错