Pytest框架
一、简介
pytest:基于unittest之上的单元测试框架
有什么特点?
- 自动发现测试模块和测试方法
- 断言更加方便,assert + 表达式,例如
assert 1 == 1
- 灵活运行指定的测试用例,标签化,适合回归、正向、冒烟、登录
- (夹具)环境管理灵活。会话、模块,哪个用,哪个不用
- 丰富的插件,例如测试报告插件
- 和unittest兼容
安装
pip install pytest
# 更新
pip install -U pytest
# 只安装到当前用户
pip install -U --user pytest
# 安装html报告的插件
pip install pytest-html
二、pytest收集测试用例的规则
-
默认从当前目录中搜集测试用例,即在哪个目录下运行pytest命令,则从哪个目录当中搜索
-
搜索规则:
- 模块名称:
test_*.py
和*_test.py
开头或者结尾,不要同时满足 - 函数名称:
test_
开头 - 类:
- 以
Test
开头的测试类(没有__init__
函数) - 如果使用了 unittest, 遵循 unittest 的规则
- 如果没有继承 unittest.TestCase, 不要使用
__init__
,一旦使用__init__
,就是一个普通的类,不会被当成测试类了
- 以
- 模块中可以只有测试方法函数,不用类,也可以识别
- 模块名称:
-
自定义查找规则:pytest.ini
[pytest] python_files = test_*.py check_ *.py python_functions = *_test python_classes = Check_*
三、fixture测试夹具——前置后置条件
1. 定义和作用
- 测试用例执行的环境准备和清理,前置条件和后置条件
- unittest中是setUp()等
2.定义fixture
- 在一个普通函数申明前加 @pytest.fixture
- 在函数内使用 yield 关键字
- 关键字以后的代码,就是环境清理的代码,即在测试用例执行完毕之后执行
3.fixture作用域
@pytest.fixture(scope="fuction")
# function:每个函数中都运行一次,默认,类比setUp
# class:每个类中运行一次,类比setUpClass
# module:每个模块中只运行一次
# session:全局只运行一次
4.调用fixture
-
在测试用例中直接调用它
def test_login(self, fixture函数名)
-
用pytest装饰器调用
@pytest.mark.usefixtures("fixture函数名字")
5.conftest.py
- 存储fixture
- 固定的文件,不需要导入
6.使用实例
conftest.py文件:
import pytest
from selenium import webdriver
@pytest.fixture(scope="fuction")
def before_test_and_after():
"""启动浏览器"""
print("正在启动浏览器")
driver = webdriver.Chrome()
yield driver # 生成器,惰性求值。
driver.quit()
test_demo.py测试用例文件:
import pytest
# 方法一:
@pytest.mark.usefixtures("before_test_and_after")
class TestAdd:
@pytest.mark.parametrize("case_info", cases)
def test_add(self,case_info):
assert case_info["expected"] == 3
四、paramtrize参数化——数据驱动
-
ddt和unittest搭配使用
-
在pytest中用@pytest.mark.paramtrize("data", cases)
cases = [ {"expected": 1}, {"expected": 2}, {"expected": 3} ] class TestAdd: @pytest.mark.parametrize("case_info", cases) def test_add(self,case_info): assert case_info["expected"] == 3
五、assert断言
直接用内置关键字, assert 条件表达式
expected = "yuz"
actual = "yuz wang"
assert expected not in actual, "这次真的断言失败了,可能是因为元素的定位问题"
六、测试报告
pytest -html插件
-
安装html报告的插件:pytest -html
pip install pytest -html
-
生成html格式的测试报告
# 命令行 pytest --html=reports est.html # python程序 if __name__ == '__main__': pytest.main(["-m invest", f"--html=reports est.html"])
allure报告插件
-
安装allure插件
- 解压后,复制bin文件所在路径,配置环江变量
- cmd中输入allure,碰到以下错误
解决:安装jdk,配置JAVA_HOME环境变量
-
安装allure-pytest 绑定包
pip install allure-pytest
-
allure的使用
- 生成测试报告
首次安装allure,需要重启,allure命令才生效
# 命令行运行 # 生成一个test_invest的文件 pytest tests est_invest.py --alluredir=reports est_invest # 预览测试报告,会生成临时报告,自动用网页打开 allure serve reports est_invest # 生成静态文件 allure generate reports est_invest
- 添加注释
七、mark 功能——用例筛选
作用:给测试用例打标签,在运行测试用例的时候,可根据标签名来过滤要运行的用例
使用步骤:
-
注册,修改pytest.ini文件
[pytest] markers = success demo linux
-
在测试方法或测试类上打标签,可以同时打多个标签
import pytest @pytest.mark.demo class TestDemo: @pytest.mark.linux @pytest.mark.success def test_demo(self): pass
-
运行用例。命令行运行
pytest -m "success" # 标签表达式 # 表达式只支持双引号,不支持单引号 pytest -m "success and demo" pytest -m "success or demo" pytest -m "success and not demo"
-
特殊标签——跳过函数
# 某个功能被废弃,不需要测试。 @pytest.mark.skip(reason="跳过原因") # 有条件地跳过某些内容 import sys @pytest.mark.skipif(sys.version_info < (3.6), reson="requires python3.6 or higher") @pytest.mark.skipif(sys.platform=="linux", reason="window系统因为环境不同跳过。")
八、pytest运行的几种方式
-
右击运行
-
命令行运行:
# 运行当前目录下的所有用例 pytest # 指定测试模块 pytest test_demo.py # 指定测试目录 pytest testing/ # 通过关键字表达式过滤执行 pytest -k "MyClass and not method" # 通过节点id来运行,节点id: 模块名::类名::函数名 pytest test_login.py::test_demo # 通过标签表达式 pytest -m "success"
-
python程序运行:
if __name__ == '__main__': # main()函数里可以加表达式 pytest.main() # pytest.main(["-m success"])
设置默认的测试用例运行器
九、重运行机制
重运行表示如果断言失败,测试用例没有通过,则重新运行一次。如果测试用例通过了,就不会重新运行。
在web自动化测试当中,元素定位, 元素操作不是很稳定,例如网络不稳定
-
安装
pip install pytest-rerunfailures
-
运行
# 执行2次 pytest --reruns 2 # 间隔5s再执行 pytest --reruns 2 --reruns-delay 5
十、打印输出信息
pytest -s
十一、pytest 和unittest的区别
- pytest支持更加丰富的插件
- pytest是第三方库,unittest是标准库,标准库是和python绑定,稳定性更强,pytest的稳定性会差一些,pytest版本和python版本不匹配
- 运行用例,管理用例更加灵活,@pytest.mark标记功能,运行时用标记表达式
- 断言更加方便和智能,用assert 关键字,而且有智能提示,预期结果和实际结果。
- 有更加灵活更加强大的环境管理,fixture
- 自动收集用例
- pytest 和 unittest 是可以兼容的,但是不是完全兼容。
- 使用了pytest的paramatrize和fixture,不能再使用unittest,强制二选一
十二、web自动化方案选择
-
方案1: 全部使用 pytest, 完全不用 unittest
-
方案2:
-
unittest 去实现测试用例方法和ddt,setUp, tearDown,
- pytest 用来运行和管理用例,mark
- allure 生成报告
-