三、Pytest框架实现前后置(固件,夹具)的处理
为什么需要这些功能?
比如:web自动化执行用例之前,请问需要打开浏览器吗?用例执行后需要关闭浏览器?[pytest] addopts = -vs testpaths = ./web_testcase/test_login.py python_files = test*.py python_classes = Test* python_functions = test markers = smoke:冒烟模块 usermanage:用户管理模块 productmanage:商品管理模块import pytest class TestLogin: # 在所有的用例之前只执行一次 def setup_class(self): print("\n在每个类执行前的初始化的工作:比如:创建日志对象,创建数据库的连接,创建接口的请求对象。") # 在每个用例之前都会执行一次 def setup_method(self): # 以前的方法是 setup 就可以了,现在是 setup_method, 否则可以通过但会警告 print("\n在执行测试用例之前初始化的代码:打开浏览器,加载网页, 类似 __init__方法") def test_login_01(self): print("\n测试WEB登录类01") def test_login_02(self): print("\n测试WEB登录类02") def teardown_method(self): # 以前是teardown就可以了,现在是teardown_method,否则可以通过但会警告 print("\n在执行测试用例之后的扫尾的代码:关闭浏览器, 类似 __str__方法") # 在所有的用例运行结束后执行一次 def teardown_class(self): print("\n在每个类执行后的扫尾的工作:比如:销毁日志对象,销毁数据库的连接,销毁接口的请求对象。")
@pytest.fixture(scope="", params="", autouse="", ids="", name="") # 1. scope:表示的是被@pytest.fixture标记的方法的作用域。function(默认),class,module,package/session. # 2. params:参数化(支持,列表[],元祖(),字典列表[{},{},{}],字典元祖({},{},{}) # 3. autouse=True:自动使用,默认False # 4. ids:当使用params参数化时,给每一个值设置一个变量名。意义不大。 # 5. name:给表示的是被@pytest.fixture标记的方法取一个别名,意义不大。
2.1 scope的作用
2.1.1 scope="function" 作用在方法的前后置( setup_method/teardown_method)
import pytest @pytest.fixture(scope="function") # 默认就是function def my_fixture(): print("\n前后置的一些方法") class TestLogin: def test_login_01(self): print("\n测试WEB登录类01") def test_login_02(self, my_fixture): print("\n测试WEB登录类02") # 这种方法只能实现前置
import pytest @pytest.fixture(scope="function") # 默认就是function def my_fixture(): print("\n前置的一些方法") yield print("\n后置的一些方法") class TestLogin: def test_login_01(self): print("\n测试WEB登录类01") def test_login_02(self, my_fixture): print("\n测试WEB登录类02") # 前置后置都是调用同一个函数,因此,在这个函数可以使用yeild来装饰成一个迭代器,等用例运行结束了,在迭代处理,就可以类似调用后置的处理了。然后再返回函数。 # 如果每个方法都需要调用前后置my_fixture函数,那么可以在每个方法后面加上 my_fixture。另外,就是在参数中加上 autouse = True 就可以了。
import pytest @pytest.fixture(scope="class", autouse=True) def my_fixture(): print("\n前置的一些方法") yield print("\n后置的一些方法") class TestLogin: def test_login_01(self): print("\n测试WEB登录类01") def test_login_02(self): print("\n测试WEB登录类02") # 在所有用例执行之前,初始化前置方法,等所有用例执行结束之后,再后置方法
import pytest @pytest.fixture(scope="class", autouse=True) def my_fixture(): print("\n前置的一些方法") yield print("\n后置的一些方法") class TestLogin01: def test_login_01(self): print("\n测试WEB01登录类01") def test_login_02(self): print("\n测试WEB01登录类02") class TestLogin02: def test_login_01(self): print("\n测试WEB02登录类01") def test_login_02(self): print("\n测试WEB02登录类02") # 当存在两个类的时候,每个类都会初始化前后置
import pytest @pytest.fixture(scope="module", autouse=True) def my_fixture(): print("\n前置的一些方法") yield print("\n后置的一些方法") class TestLogin01: def test_login_01(self): print("\n测试WEB01登录类01") def test_login_02(self): print("\n测试WEB01登录类02") class TestLogin02: def test_login_01(self): print("\n测试WEB02登录类01") def test_login_02(self): print("\n测试WEB02登录类02") # 使用module的时候,不管文件中有多少个类,都只会初始化一次前后置
import pytest @pytest.fixture(scope="function", params=["123", "234", "345"]) def my_fixture(): print("\n前置的一些方法") yield print("\n后置的一些方法") class TestLogin01: def test_login_01(self): print("\n测试WEB01登录类01") def test_login_02(self, my_fixture): print("\n测试WEB01登录类02") print("----------" + str(my_fixture)) # 存在三个参数,方法就会被执行三次,问题是参数并没有传递过去
import pytest @pytest.fixture(scope="function", params=["123", "234", "345"]) def my_fixture(): return "success" # 被fixture标记的函数,可以这样直接传递结果,传递过后会被调用的位置的参数接收 class TestLogin01: def test_login_01(self): print("\n测试WEB01登录类01") def test_login_02(self, my_fixture): print("\n测试WEB01登录类02 print("----------" + str(my_fixture))
# 当我们想要将参数传递过去的时候,使用request.param 固定用法。 import pytest @pytest.fixture(scope="function", params=["123", "234", "345"]) def my_fixture(request): return request.param # 固定用法 class TestLogin01: def test_login_01(self): print("\n测试WEB01登录类01") def test_login_02(self, my_fixture): print("\n测试WEB01登录类02") print("----------" + str(my_fixture))
# 当前后置与传递参数同时使用的情况,发现前后置成功了,但是参数并没有传递成功,因此可以通过yield传递参数 import pytest @pytest.fixture(scope="function", params=["123", "234", "345"]) def my_fixture(request): print("\n前置的一些方法") yield print("\n后置的一些方法") return request.param class TestLogin01: def test_login_01(self): print("\n测试WEB01登录类01") def test_login_02(self, my_fixture): print("\n测试WEB01登录类02") print("----------" + str(my_fixture))
# 使用yield传递参数,和前后置同时使用,就能完美实现功能 import pytest @pytest.fixture(scope="function", params=["123", "234", "345"]) def my_fixture(request): print("\n前置的一些方法") yield request.param print("\n后置的一些方法") class TestLogin01: def test_login_01(self): print("\n测试WEB01登录类01") def test_login_02(self, my_fixture): print("\n测试WEB01登录类02") print("----------" + str(my_fixture))
import pytest @pytest.fixture(scope="function", autouse=True) def my_fixture(): print("\n前置的一些方法") yield print("\n后置的一些方法") class TestLogin: def test_login_01(self): print("\n测试WEB登录类01") def test_login_02(self): print("\n测试WEB登录类02") # 如果每个方法都需要调用前后置my_fixture函数,那么可以在每个方法后面加上 my_fixture。另外,就是在参数中加上 autouse = True 就可以了。
import pytest @pytest.fixture(scope="function", params=["123", "234", "345"], ids=["01", "02", "03"]) def my_fixture(request): print("\n前置的一些方法") yield request.param print("\n后置的一些方法") class TestLogin01: def test_login_01(self): print("\n测试WEB01登录类01") def test_login_02(self, my_fixture): print("\n测试WEB01登录类02") print("----------" + str(my_fixture))
# 使用name之后,原本的变量名my_fixture传参就不能使用了 import pytest @pytest.fixture(scope="function", params=["123", "234", "345"], ids=["01", "02", "03"], name="AAA") def my_fixture(request): print("\n前置的一些方法") yield request.param print("\n后置的一些方法") class TestLogin01: def test_login_01(self): print("\n测试WEB01登录类01") def test_login_02(self, AAA): print("\n测试WEB01登录类02") print("----------" + str(AAA))
# 在项目中 my_fixture 并不是和代码在一个文件中,因为 my_fixture的作用域只能在当前文件中,所以一般通过conftest.py和@pytest.fixture()结合使用实现全局的前置应用(比如:
# 项目的全局登录,模块的全局处理),可以理解为将 my_fixture的代码放在 conftest.py 中 1. conftest.py文件是单独存放的一个夹具配置文件,名称是不能更改。 2. 用处可以在不同的py文件中使用同一个fixture函数。 3. 原则上conftest.py需要和运行的用例放到统一层。并且不需要做任何的imprt导入的操作。修改项目架构如下:
# testcase/interface_testcase/conftest.py import pytest @pytest.fixture(scope="function") def interface_fixture(): print("\n接口前置的一些方法") yield print("\n接口后置的一些方法")# testcase\interface_testcase\test_interface.py def test_interface(interface_fixture): print("测试接口函数") print("----------" + str(interface_fixture)) class TestInterfaceCase: def test_interface(self, interface_fixture): print("测试接口类方法") print("----------" + str(interface_fixture))# testcase\web_testcase\conftest.py import pytest @pytest.fixture(scope="function") def web_fixture(): print("\nWEB前置的一些方法") yield print("\nWEB后置的一些方法")# testcase\web_testcase\test_web.py class TestWebCase: def test_web_01(self): print("\n测试WEB类方法01") def test_web_02(self, all_fixture, web_fixture): print("\n测试WEB类方法02") print("----------" + str(all_fixture)) print("----------" + str(web_fixture))# testcase\conftest.py import pytest @pytest.fixture(scope="function") def all_fixture(): print("\n全局前置的一些方法") yield print("\n全局后置的一些方法")# all.py import pytest if __name__ == '__main__': pytest.main()[pytest] addopts = -vs testpaths = ./ python_files = test*.py python_classes = Test* python_functions = test markers = smoke:冒烟模块 usermanage:用户管理模块 productmanage:商品管理模块
















浙公网安备 33010602011771号