参考文件
1、文件规范
(1)文件命名以test_开头或者_test结尾,例如test_demo1.py、demo2_test.py
(2)根目录创建pytest.ini中进行一些属性的配置来修改 pytest 的默认属性
[pytest] #参数 addopts = ‐vs # 默认的执行路径,它会默认执行该文件夹下所有的满足条件的测试case testpaths = ./testcases # 文件命名规则 python_files = test_*.py # 类名命名规则 python_classes = Test* # Case命名规则 python_functions = test_* # 标记 markers = # 冒烟规则 smoke:冒烟用例 product_manage:商品管理
[pytest] markers = user_manage: this is user_manage product_manage: this is product_manage
(3)运行命令
# -vs: -v输出详细信息 -s输出调试信息 pytest -vs # -n: 多线程运行(前提安装插件:pytest-xdist) pytest -vs -n=2 # --reruns num: 失败重跑(前提安装插件:pytest-rerunfailres) pytest -vs --reruns=2 # -x: 出现一个用例失败则停止测试 pytest -vs -x # --maxfail: 出现几个失败才终止 pytest -vs --maxfail=2 # --html: 生成html的测试报告,后面 需要跟上所创建的文件位置及文件名称(前提安装插件:pytest-html) pytest -vs --html ./reports/result.html # -k: 运行测试用例名称中包含某个字符串的测试用例,我们可以采用or表示或者,采用and表示都 pytest -vs -k "qiuluo" pytest -vs -k "qiuluo or weiliang" pytest -vs -k "qiuluo and weiliang" # -m:冒烟用例执行,后面需要跟一个冒烟名称,执行user_manage这个分组 pytest -vs -m user_manage
2、相关示例
(1)分组@pytest.mark.user_manage
import pytest class TestDemo: @pytest.mark.user_manage def test_demo1(self): print("user_manage_test1") @pytest.mark.product_manage def test_demo2(self): print("product_manage_test1") @pytest.mark.user_manage @pytest.mark.product_manage def test_demo3(self): print("manage_test1") # 运行user_manage分组 pytest -m user_manage # 运行并展示输出内容 pytest -m user_manage -s # 运行并查看跳过的日志 pytest test_1.py -rs # 运行并增加日志详细程度 pytest test_1.py -s -v
(2)前后置方法
前后置就是针对不同层级方法执行前和执行后所需要执行的步骤进行封装并执行
这个层级通常被划分为:文件层、类层、方法层(比如说要执行打印日志操作)
方法层:它会在每个方法执行前后去执行该操作
# 前置-用例执行之前 def setup_method(self): print("用例之前执行的代码") # 后置-用例执行之后 def teardown_method(self): print("用例之后执行的代码")
类层:它会在调用这个类内所有方法的前后去执行该操作,无论类的方法执行多少次,它只会调用一次,它是一个类方法
# 类之前 def setup_class(self): print("类之前执行") # 类之后 def teardown_class(self): print("类之后执行")
文件层:也叫模块层,在每个代码文件执行前后去执行该操作,模块级别的需要卸载类的外边直接定义函数即可
# 代码文件之前 def setup_module(): print("代码文件之前") pass # 代码文件之后 def teardown_module(): print("代码文件之后") pass
# 如果只有一个方法,然后这个方法被跳过了,那么运行后setup和teardown都不会执行 # 只有当有一个方法没有跳过时,setup和teardown才会执行 import pytest class TestDemo: workage2 = 5 workage3 = 20 def setup_method(self, method): print("之前") def teardown_method(self, method): print("之后") @pytest.mark.skipif(workage2 < 10, reason="工作经验少于10年跳过") def test_demo2(self): print("2经验可以了") @pytest.mark.skipif(workage3 < 15, reason="工作经验少于15年跳过") def test_demo3(self): print("3经验可以了")
(3)当测试类内的每一个测试方法都调用了fixture,fixture只在该class下所有测试用例执行前执行一次
import pytest @pytest.fixture(scope='class') def login(): print("scope为class") class TestLogin: def test_1(self, login): print("用例1") def test_2(self, login): print("用例2") def test_3(self, login): print("用例3")
这个代码中login会在class类之前运行
完整用例
# login.py class UserAuth: def __init__(self): self.user_data = { 'username': 'testuser', 'password': 'securepassword' } def login(self, username, password): if username == self.user_data['username'] and password == self.user_data['password']: return True return False # test_main.py import pytest from login import UserAuth class TestUserAuth: def setup_method(self, method): self.auth = UserAuth() print("Setup before each test") def teardown_method(self, method): print("Teardown after each test") def test_login_success(self): assert self.auth.login('testuser', 'securepassword') == True, "Login should succeed with correct credentials" def test_login_wrong_username(self): assert self.auth.login('wronguser', 'securepassword') == False, "Login should fail with wrong username" def test_login_wrong_password(self): assert self.auth.login('testuser', 'wrongpassword') == False, "Login should fail with wrong password" def test_login_empty_username(self): assert self.auth.login('', 'securepassword') == False, "Login should fail with empty username" def test_login_empty_password(self): assert self.auth.login('testuser', '') == False, "Login should fail with empty password" if __name__ == "__main__": pytest.main(["-s", __file__])