Pytest前后置处理

Pytest前后置处理

Pytest框架实现一些前后置的处理,常用三种。

1.setup/teardown,setup_class/teardown_class

使用场景:用例执行之前,需要做初始化操作;用例执行结束之后,需要做资源清理
总配置文件pytest.ini

[pytest]
addopts = -vs
testpaths = testcase/test_setup_teardown.py
python_files = test_*.py
python_classes = Test*
python_functions = test
1.1、setup/teardown

测试用例:

# -*- coding: UTF-8 -*-
class TestSetupTeardown:
    def setup(self):
        print('\n在执行测试用例之前初始化的代码')

    def test_01_login(self):
        print('\n登录')

    def test_02_browse(self):
        print('\n浏览网页')

    def test_03_exit(self):
        print('\n退出')

    def teardown(self):
        print('\n清理资源')

命令行操作:

% pytest
============================================================================= test session starts =============================================================================
platform darwin -- Python 3.7.9, pytest-6.2.4, py-1.10.0, pluggy-0.13.1 -- /Users/xxx/opt/anaconda3/envs/py37/bin/python
cachedir: .pytest_cache
metadata: {'Python': '3.7.9', 'Platform': 'Darwin-20.2.0-x86_64-i386-64bit', 'Packages': {'pytest': '6.2.4', 'py': '1.10.0', 'pluggy': '0.13.1'}, 'Plugins': {'xdist': '2.3.0', 'html': '3.1.1', 'ordering': '0.6', 'rerunfailures': '10.1', 'metadata': '1.11.0', 'forked': '1.3.0'}}
rootdir: /Users/xxx/PycharmProjects/pytestDemo, configfile: pytest.ini, testpaths: testcase/test_setup_teardown.py
plugins: xdist-2.3.0, html-3.1.1, ordering-0.6, rerunfailures-10.1, metadata-1.11.0, forked-1.3.0
collected 3 items                                                                                                                                                             

testcase/test_setup_teardown.py::TestSetupTeardown::test_01_login 
在执行测试用例之前初始化的代码

登录
PASSED
清理资源

testcase/test_setup_teardown.py::TestSetupTeardown::test_02_browse 
在执行测试用例之前初始化的代码

浏览网页
PASSED
清理资源

testcase/test_setup_teardown.py::TestSetupTeardown::test_03_exit 
在执行测试用例之前初始化的代码

退出
PASSED
清理资源


============================================================================== 3 passed in 0.01s ==============================================================================
1.2、setup_class/teardown_class

测试用例:

# -*- coding: UTF-8 -*-
class TestSetupTeardown:
    def setup_class(self):
        """
        在所有的用力之前只执行一次
        :return:
        """
        print('\n在每个类执行前的初始化操作。比如:创建日志对象,创建数据库的连接,创建接口的请求对象')

    def test_01_login(self):
        print('登录')

    def test_02_browse(self):
        print('\n浏览网页')

    def test_03_exit(self):
        print('\n退出')

    def teardown_class(self):
        print('\n在每个类执行后的扫尾工作。比如:销毁日志对象,销毁数据库的连接,销毁接口的请求对象。')

命令行操作:

% pytest
============================================================================= test session starts =============================================================================
platform darwin -- Python 3.7.9, pytest-6.2.4, py-1.10.0, pluggy-0.13.1 -- /Users/xxx/opt/anaconda3/envs/py37/bin/python
cachedir: .pytest_cache
metadata: {'Python': '3.7.9', 'Platform': 'Darwin-20.2.0-x86_64-i386-64bit', 'Packages': {'pytest': '6.2.4', 'py': '1.10.0', 'pluggy': '0.13.1'}, 'Plugins': {'xdist': '2.3.0', 'html': '3.1.1', 'ordering': '0.6', 'rerunfailures': '10.1', 'metadata': '1.11.0', 'forked': '1.3.0'}}
rootdir: /Users/xxx/PycharmProjects/pytestDemo, configfile: pytest.ini, testpaths: testcase/test_setup_teardown.py
plugins: xdist-2.3.0, html-3.1.1, ordering-0.6, rerunfailures-10.1, metadata-1.11.0, forked-1.3.0
collected 3 items                                                                                                                                                             

testcase/test_setup_teardown.py::TestSetupTeardown::test_01_login 
在每个类执行前的初始化操作。比如:创建日志对象,创建数据库的连接,创建接口的请求对象
登录
PASSED
testcase/test_setup_teardown.py::TestSetupTeardown::test_02_browse 
浏览网页
PASSED
testcase/test_setup_teardown.py::TestSetupTeardown::test_03_exit 
退出
PASSED
在每个类执行后的扫尾工作。比如:销毁日志对象,销毁数据库的连接,销毁接口的请求对象。


============================================================================== 3 passed in 0.01s ==============================================================================

2、使用@pytest.fixture()装饰器来实现部分用例的前后置

@pytest.fixture(scope=‘function’, params=’’, autouse=’’, ids=’’, name=’’)

  • scope表示的是被@pytest.fixture标记的方法的作用域。function(默认)、class、module、package/session
  • params:参数化(支持:列表[],元祖(),字典列表[{},{},{}],字典元组({},{},{}))
  • autouse=True:自动执行,默认False
  • ids:当使用params参数化时,给每一个值设置一个变量名。意义不大
  • name:给被@pytest.fixture标记的方法取一个别名
2.1、scope是function

手动调用前后置方法,好处是想让哪些方法执行前后置就让哪些方法执行前后置
用例:

# -*- coding: UTF-8 -*-
import pytest

@pytest.fixture(scope='function')
def my_fixture():
    print('这是前置的方法,可以实现部分以及全部用例的前置')
    yield	# 通过yield将前后置方法分隔
    print('\n这是后置的方法,可以实现部分以及全部用例的后置')


class TestSetupTeardown:

    def test_01(self):
        print('没有前置方法')

    def test_02(self, my_fixture):	# 调用处
        print('有前置方法')

命令行操作:

 % pytest
============================================================================= test session starts =============================================================================
platform darwin -- Python 3.7.9, pytest-6.2.4, py-1.10.0, pluggy-0.13.1 -- /Users/xxx/opt/anaconda3/envs/py37/bin/python
cachedir: .pytest_cache
metadata: {'Python': '3.7.9', 'Platform': 'Darwin-20.2.0-x86_64-i386-64bit', 'Packages': {'pytest': '6.2.4', 'py': '1.10.0', 'pluggy': '0.13.1'}, 'Plugins': {'xdist': '2.3.0', 'html': '3.1.1', 'ordering': '0.6', 'rerunfailures': '10.1', 'metadata': '1.11.0', 'forked': '1.3.0'}}
rootdir: /Users/liyabin01/PycharmProjects/pytestDemo, configfile: pytest.ini, testpaths: testcase/test_fixture.py
plugins: xdist-2.3.0, html-3.1.1, ordering-0.6, rerunfailures-10.1, metadata-1.11.0, forked-1.3.0
collected 2 items                                                                                                                                                             

testcase/test_fixture.py::TestSetupTeardown::test_01 没有前置方法
PASSED
testcase/test_fixture.py::TestSetupTeardown::test_02 这是前置的方法,可以实现部分以及全部用例的前置
有前置方法
PASSED
这是后置的方法,可以实现部分以及全部用例的后置


============================================================================== 2 passed in 0.01s ==============================================================================

自动调用前后置方法,好处是方法可以自动执行,但是不能控制哪些执行哪些不执行,全部作用域命中的方法都要执行
用例:

# -*- coding: UTF-8 -*-
import pytest
@pytest.fixture(scope='function', autouse=True)	# 调用处
def my_fixture():
    print('这是前置的方法,可以实现部分以及全部用例的前置')
    yield
    print('\n这是后置的方法,可以实现部分以及全部用例的后置')
class TestSetupTeardown:
    def test_01(self):
        print('没有前置方法')
    def test_02(self):
        print('有前置方法')

命令行操作,会发现test_01方法也加了前后置处理

% pytest
============================================================================= test session starts =============================================================================
platform darwin -- Python 3.7.9, pytest-6.2.4, py-1.10.0, pluggy-0.13.1 -- /Users/xxx/opt/anaconda3/envs/py37/bin/python
cachedir: .pytest_cache
metadata: {'Python': '3.7.9', 'Platform': 'Darwin-20.2.0-x86_64-i386-64bit', 'Packages': {'pytest': '6.2.4', 'py': '1.10.0', 'pluggy': '0.13.1'}, 'Plugins': {'xdist': '2.3.0', 'html': '3.1.1', 'ordering': '0.6', 'rerunfailures': '10.1', 'metadata': '1.11.0', 'forked': '1.3.0'}}
rootdir: /Users/liyabin01/PycharmProjects/pytestDemo, configfile: pytest.ini, testpaths: testcase/test_fixture.py
plugins: xdist-2.3.0, html-3.1.1, ordering-0.6, rerunfailures-10.1, metadata-1.11.0, forked-1.3.0
collected 2 items                                                                                                                                                             

testcase/test_fixture.py::TestSetupTeardown::test_01 这是前置的方法,可以实现部分以及全部用例的前置
没有前置方法
PASSED
这是后置的方法,可以实现部分以及全部用例的后置

testcase/test_fixture.py::TestSetupTeardown::test_02 这是前置的方法,可以实现部分以及全部用例的前置
有前置方法
PASSED
这是后置的方法,可以实现部分以及全部用例的后置


============================================================================== 2 passed in 0.01s ==============================================================================
2.2、scope是class

fixture为class级别的时候,如果一个class里面有多个用例,都调用了此fixture,那么此fixture只在该class里所有用例开始前执行一次
(1)验证执行次数
用例:

# -*- coding: UTF-8 -*-
import pytest

@pytest.fixture(scope="class")
def first():
    print("\n获取用户名,scope为class级别只运行一次")
    a = "yoyo"
    return a

class TestCase():
    def test_1(self, first):
        '''用例传fixture'''
        print("测试账号:%s" % first)
        assert first == "yoyo"

    def test_2(self, first):
        '''用例传fixture'''
        print("测试账号:%s" % first)
        assert first == "yoyo"

命令行操作:

% pytest
testcase/test_fixture.py::TestCase::test_1 
获取用户名,scope为class级别只运行一次
测试账号:yoyo
PASSED
testcase/test_fixture.py::TestCase::test_2 测试账号:yoyo
PASSED

(2)验证作用域
用例:

# -*- coding: UTF-8 -*-
import pytest
@pytest.fixture(scope='class', autouse=True)
def my_fixture():
    print('\n这是前置的类方法,可以实现部分以及全部用例的前置')
    yield
    print('\n这是后置的类方法,可以实现部分以及全部用例的后置')
class TestSetupTeardown1:
    def test_01(self):
        print('我是测试方法1')
class TestSetupTeardown2:
    def test_02(self):
        print('我是测试方法2')

命令行操作:

% pytest
============================================================================= test session starts =============================================================================
platform darwin -- Python 3.7.9, pytest-6.2.4, py-1.10.0, pluggy-0.13.1 -- /Users/xxx/opt/anaconda3/envs/py37/bin/python
cachedir: .pytest_cache
metadata: {'Python': '3.7.9', 'Platform': 'Darwin-20.2.0-x86_64-i386-64bit', 'Packages': {'pytest': '6.2.4', 'py': '1.10.0', 'pluggy': '0.13.1'}, 'Plugins': {'xdist': '2.3.0', 'html': '3.1.1', 'ordering': '0.6', 'rerunfailures': '10.1', 'metadata': '1.11.0', 'forked': '1.3.0'}}
rootdir: /Users/liyabin01/PycharmProjects/pytestDemo, configfile: pytest.ini, testpaths: testcase/test_fixture.py
plugins: xdist-2.3.0, html-3.1.1, ordering-0.6, rerunfailures-10.1, metadata-1.11.0, forked-1.3.0
collected 2 items                                                                                                                                                             

testcase/test_fixture.py::TestSetupTeardown1::test_01 
这是前置的类方法,可以实现部分以及全部用例的前置
我是测试方法1
PASSED
这是后置的类方法,可以实现部分以及全部用例的后置

testcase/test_fixture.py::TestSetupTeardown2::test_02 
这是前置的类方法,可以实现部分以及全部用例的前置
我是测试方法2
PASSED
这是后置的类方法,可以实现部分以及全部用例的后置


============================================================================== 2 passed in 0.01s ==============================================================================
2.3、params

简单用例:

# -*- coding: UTF-8 -*-
import pytest

@pytest.fixture(scope='function', params=['成龙', '甄子丹', '李小龙'])
def get_data(request):
    return request.param

class TestFixture:

    def test_01(self):
        print('我是吴奇隆')

    def test_02(self, get_data):
        print('我是{}'.format(get_data))

命令行操作:

% pytest
testcase/test_fixture.py::TestFixture::test_01 我是吴奇隆
PASSED
testcase/test_fixture.py::TestFixture::test_02[\u6210\u9f99] 我是成龙
PASSED
testcase/test_fixture.py::TestFixture::test_02[\u7504\u5b50\u4e39] 我是甄子丹
PASSED
testcase/test_fixture.py::TestFixture::test_02[\u674e\u5c0f\u9f99] 我是李小龙
PASSED

可以观察到test_02方法调用了三次,固定写法。

3、通过conftest.py和@pytest.fixture()结合实现全局的前置应用(比如:项目的全局登录,模块的全局处理)

1.conftest.py文件是单独存放的一个夹具(@pytest.fixture())配置文件,名称不能更改。
2.用处可以在不同的py文件中使用同一个fixture函数
3.原则上conftest.py需要和运行的用例放在同一层。并且不需要做任何的import导入操作。
总结:

  • setup/teardown,setup_class/teardown_class:它是作用域所有用例或者所有类
  • @pytest.fixture():它的作用是既可以部分也可以全部前后置
  • conftest.py和@pytest.fixture()结合使用,作用域全局的前后置。
    用例:
    pytest.ini
[pytest]
addopts = -vs
testpaths = testcase/
python_files = test_*.py
python_classes = Test*
python_functions = test

项目目录结构:
在这里插入图片描述
conftest.py

import pytest

@pytest.fixture(scope='function')	# conftest.py
def all_fixture():
    print('\n全局的前置')
    yield
    print('\n全局的后置')

@pytest.fixture(scope='function')	# product/conftest.py
def product_fixture():
    print('\nproduct的前置')
    yield
    print('\nproduct的后置')

@pytest.fixture(scope='function')	# user/conftest.py
def user_fixture():
    print('\nuser的前置')
    yield
    print('\nuser的后置')

test_product.py/test_user.py

import pytest

class TestProduct:
    def test_product(self, all_fixture, product_fixture):
        print('我是一个product~')

class TestUser:
    def test_user(self, user_fixture):
        print('我是一个user~')

命令行操作:

% pytest
============================================================================= test session starts =============================================================================

collected 2 items                                                                                                                                                             

testcase/product/test_product.py::TestProduct::test_product 
全局的前置

product的前置
我是一个product~
PASSED
product的后置

全局的后置

testcase/user/test_user.py::TestUser::test_user 
user的前置
我是一个user~
PASSED
user的后置


============================================================================== 2 passed in 0.02s ==============================================================================

上述执行结果可以看出,@pytest.fixture的生效顺序是函数中调用的顺序
def test_product(self, all_fixture, product_fixture)

  • 2
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值