前言
一般情况下我们习惯使用 setup 和 teardown 来进行执行用例前的初始化。但是有时我们实际涉及到的业务可能会更复杂更灵活,使用setup 和 teardown也不足以满足我们的需求。
将 fixture 作为函数参数
例如:
测试用例 1 需要依赖登录功能,测试用例 2 不需要登录功能,测试用例 3 需要登录功能。这种场景 就需要使用 pytest fixture 功能,在方法前面加个上@pytest.fixture
装饰器,加了这个装饰器的方法可以以参数的形式传入到方法里面执行。
# Author xuejie zeng # encoding utf-8 import pytest @pytest.fixture() def login(): print("输入登录的用户名和密码") return ('username','password') def test_1(login): print(login) print("test_1,需要登录") def test_2(): print("test_2,不需要登录 ")
运行结果:
test_fixture.py::test_1 输入登录的用户名和密码 ('username', 'password') test_1,需要登录 PASSED test_fixture.py::test_2 test_2,不需要登录 PASSED test_fixture.py::test_3 输入登录的用户名和密码 ('username', 'password') test_case3,需要登录 PASSED
从上面的结果可以看出,test_1 和 test_3 运行之前执行了 login 方法,test_2 没有执行这个方法, 因为test_1 和 test_3 分别增加了 login 方法名作为参数,pytest 会发现并调用 @pytest.fixture
标记的 login 功能。
fixture的参数介绍
fixture 里面有一个参数 scope,通过 scope 可以控制 fixture 的作用范围,根据作用范围大小划分:session> module> class> function,具体作用范围如下:
-
function 函数或者方法级别都会被调用
-
class 类级别调用一次
-
module 模块级别调用一次
-
session 是多个文件调用一次(可以跨.py文件调用,每个.py文件就是module)
function 函数
# Author xuejie zeng # encoding utf-8 import pytest @pytest.fixture(scope='function') #不带参数时默认是function级别 def login(): print("输入登录的用户名和密码") return ('username','password') def test_1(login): print(login) print("test_1,需要登录") def test_2(): print("test_2,不需要登录 ") def test_3(login): print(login) print("test_case3,需要登录")
运行结果:
test_fixture.py::test_1 输入登录的用户名和密码 ('username', 'password') test_1,需要登录 PASSED test_fixture.py::test_2 test_2,不需要登录 PASSED test_fixture.py::test_3 输入登录的用户名和密码 ('username', 'password') test_case3,需要登录 PASSED
class 类级别
# Author xuejie zeng # encoding utf-8 import pytest #fixture为class级别的时候,如果一个class里面有多个用例,都调用了此fixture,那么此fixture只在该class里所有用例开始前执行一次。 @pytest.fixture(scope='class') def login(): print("输入登录的用户名和密码") return ('username','password') class Test_login(): def test_1(self,login): print("test_1,需要登录") def test_2(self,login): print("test_2,需要登录 ") def test_3(self): print("test_case3,不需要登录")
运行结果:
test_fixture.py::Test_login::test_1 输入登录的用户名和密码 #虽然test_1和test_2都添加了login方法实际上只在用例之前运行了这一次。
test_1,需要登录
PASSED
test_fixture.py::Test_login::test_2 test_2,需要登录
PASSED
test_fixture.py::Test_login::test_3 test_case3,不需要登录
PASSED
module 级别
# Author xuejie zeng # encoding utf-8 import pytest #fixture为module级别时在当前.py脚本里面所有用例开始前只执行一次 @pytest.fixture(scope='module') def login(): print("输入登录的用户名和密码") return ('username','password') class Test_login(): def test_1(self,login): print("test_1,需要登录") def test_2(self,login): print("test_2,需要登录 ") def test_3(self): print("test_case3,不需要登录") class Test_login2(): def test_1(self,login): print("test_11,不需要登录") def test_2(self,login): print("test_22,不需要登录 ")
运行结果:
test_fixture.py::Test_login::test_1 输入登录的用户名和密码 #只在.py文件下运行一次
test_1,需要登录
PASSED
test_fixture.py::Test_login::test_2 test_2,需要登录
PASSED
test_fixture.py::Test_login::test_3 test_case3,不需要登录
PASSED
test_fixture.py::Test_login2::test_1 test_11,不需要登录
PASSED
test_fixture.py::Test_login2::test_2 test_22,不需要登录
PASSED
session 级别
scope=session''' '''fixture为session级别是可以跨.py模块调用的,当我们有多个.py文件的用例时候,如果多个用例只需调用一次fixture,那就可以设置为scope="session",结合conftest.py文件里使用''
'''conftest.py文件名称是固定的,pytest会自动识别该文件。放到工程的根目录下,就可以全局调用了,如果放到某个package包下,那就只在该package内有效'''
关注个人公众号:测试开发进阶之路