Pytest中fixture的作用范围(六)
- 2019 年 10 月 7 日
- 笔记
前面介绍了fixture的参数化,以及conftest.py的系列知识,本文章主要总结fixture的参数scope,通过它可以指定fixture的作用范围。scope的参数主要应用于控制fixture执行配置和销毁逻辑的频率。在scope的参数中主要有四个值可以选择,分别是function(函数级别),class(类级别).module(模块级别),session(会话级别),它的默认值是函数级别。下面依据各个案例来说明该参数的实际应用。
先来看函数级别,也就是说函数级别中,每个测试函数只需要执行一次,配置代码在测试用例运行前执行,销毁代码是在测试用例运行之后执行。见案例代码:
#!/usr/bin/python3 #coding:utf-8 import pytest @pytest.fixture(scope='function') def api(): print('开始执行') yield print('结束执行') def test_login_001(api): assert 1==1
该fixture仅仅是函数级别的应用,不会应用于其他的方面,见执行后的结果信息:
platform darwin -- Python 3.7.4, pytest-4.0.2, py-1.8.0, pluggy-0.12.0 rootdir: /Applications/code/stack/study/xunit/scope, inifile: plugins: html-1.22.0, allure-adaptor-1.7.10, metadata-1.8.0 collected 1 item test_001.py SETUP F api test_001.py::test_login_001 (fixtures used: api). TEARDOWN F api
下来看类级别的,类级别的主要指的是每个测试类需要运行一次,无论测试类里面有多少个测试方法,都会被执行到并且共享fixture,见案例代码:
#!/usr/bin/python3 #coding:utf-8 import pytest @pytest.fixture(scope='class') def api(): print('开始执行') yield print('结束执行') class TestLogin(object): def test_login_001(self,api): assert 1==1 def test_login_002(self): assert 1==1
见执行后的结果信息:
platform darwin -- Python 3.7.4, pytest-4.0.2, py-1.8.0, pluggy-0.12.0 rootdir: /Applications/code/stack/study/xunit/scope, inifile: plugins: html-1.22.0, allure-adaptor-1.7.10, metadata-1.8.0 collected 2 items test_001.py SETUP C api test_001.py::TestLogin::test_login_001 (fixtures used: api). test_001.py::TestLogin::test_login_002 (fixtures used: api). TEARDOWN C api
来来看模块级别的,在模块级别的fixture每个模块只需要执行一次,无论模块里面有多少个测试函数,类方法,都可以共享这个fixture,见案例代码:
import pytest @pytest.fixture(scope='module') def api(): print('开始执行') yield print('结束执行') def test_login_001(api): assert 1==1 class TestApi(object): def test_api_001(self,api): assert 1==1
见执行后的输出信息:
platform darwin -- Python 3.7.4, pytest-4.0.2, py-1.8.0, pluggy-0.12.0 rootdir: /Applications/code/stack/study/xunit/scope, inifile: plugins: html-1.22.0, allure-adaptor-1.7.10, metadata-1.8.0 collected 2 items test_001.py SETUP M api test_001.py::test_login_001 (fixtures used: api). test_001.py::TestApi::test_api_001 (fixtures used: api). TEARDOWN M api
是否存在这样的一个疑问,函数级别的是否可以应用在类级别,类级别的是否可以应用于函数级别了,见测试代码:
import pytest @pytest.fixture(scope='function') def api(): print('开始执行') yield print('结束执行') def test_login_001(api): assert 1==1 class TestApi(object): def test_api_001(self,api): assert 1==1
见输出的信息:
platform darwin -- Python 3.7.4, pytest-4.0.2, py-1.8.0, pluggy-0.12.0 rootdir: /Applications/code/stack/study/xunit/scope, inifile: plugins: html-1.22.0, allure-adaptor-1.7.10, metadata-1.8.0 collected 2 items test_001.py SETUP F api test_001.py::test_login_001 (fixtures used: api). TEARDOWN F api SETUP F api test_001.py::TestApi::test_api_001 (fixtures used: api). TEARDOWN F api
最后一个是会话级别的,会话级别的fixture每次会话只需要运行一次,一次pytest会话中的所有测试函数,方法都可以共享该fixture,见案例代码:
#!/usr/bin/python3 #coding:utf-8 import pytest @pytest.fixture(autouse=True,scope='session') def wuya(): print('start') yield print('end')
见测试的代码:
#!/usr/bin/python3 #coding:utf-8 import pytest def test_login_001(): assert 1==1 class TestApi(object): def test_api_001(self): assert 1==1
见执行后输出的结果信息:
platform darwin -- Python 3.7.4, pytest-4.0.2, py-1.8.0, pluggy-0.12.0 rootdir: /Applications/code/stack/study/xunit/scope, inifile: plugins: html-1.22.0, allure-adaptor-1.7.10, metadata-1.8.0 collected 2 items test_001.py SETUP S wuya test_001.py::test_login_001 (fixtures used: wuya). test_001.py::TestApi::test_api_001 (fixtures used: wuya). TEARDOWN S wuya
在pytest中也可以使用userfixture指定多个fixture,这样来标记测试函数或者测试的类,使用usefixture,需要在一个参数中指定一个或者多个fixture字符串,这样的一个场景在特定的场景下还是可以的,见案例的测试代码:
#!/usr/bin/python3 #coding:utf-8 import pytest @pytest.fixture() def api(): return 1 @pytest.fixture() def init(): print('start') yield print('end') @pytest.mark.usefixtures('api','init') def test_login_001(api): assert api==1
见执行后输出的信息:
platform darwin -- Python 3.7.4, pytest-4.0.2, py-1.8.0, pluggy-0.12.0 rootdir: /Applications/code/stack/study/xunit/scope, inifile: plugins: html-1.22.0, allure-adaptor-1.7.10, metadata-1.8.0 collected 1 item test_001.py SETUP F api SETUP F init test_001.py::test_login_001 (fixtures used: api, init). TEARDOWN F init TEARDOWN F api
在如上的结果信息中,就可以看到,测试函数共享了两个fixture。
在前面使用fixture的时候说到了autouse的选项,也应该看到,如果不使用该选项,每次共享fixture都需要指定,但是使用了它后就不需要指定了,那么标准的说法应该是:依据选项autouse=True,使作用域内的测试函数都执行该fixture,这与那些需要多次执行,但不依赖任何的状态或者外部数据的代码配合的比较好。针对如上的代码修改,见修改后的源码:
#!/usr/bin/python3 #coding:utf-8 import pytest @pytest.fixture(autouse=True) def api(): return 1 @pytest.fixture(autouse=True) def init(): print('start') yield print('end') def test_login_001(api): assert api==1
见执行后输出的结果信息:
platform darwin -- Python 3.7.4, pytest-4.0.2, py-1.8.0, pluggy-0.12.0 rootdir: /Applications/code/stack/study/xunit/scope, inifile: plugins: html-1.22.0, allure-adaptor-1.7.10, metadata-1.8.0 collected 1 item test_001.py SETUP F api SETUP F init test_001.py::test_login_001 (fixtures used: api, init). TEARDOWN F init TEARDOWN F api