目录[-]
主要流程
1.安装pytest:pip install pytest
2.基础用法
2.1最简单的示例
# coding=utf-8
import pytest
def add(a,b):
return a+b
class Test_pp:
def test_add(self):
assert add(1,2)==3
@pytest.mark.parametrize("a,b,expected",[(1,2,3),(10,10.5,20.5),(-10.3,2,500)])
def test_add2(self,a,b,expected):
assert add(a,b)==expected
返回结果:单元测试执行了3个用例,第1个是测试函数,其余2个是测试类
2.2 断言
def test_assertions():
# 相等
assert "hello" == "hello"
# 包含
assert "ello" in "hello"
# 异常
with pytest.raises(ZeroDivisionError):
1 / 0
# 类型检查
assert isinstance(42, int)
# 近似相等
assert 0.1 + 0.2 == pytest.approx(0.3)
3.主要流程
3.1 测试发现
pytest 会自动发现:
- 文件名以 test_ 开头的文件
- 以 _test.py 结尾的文件
- 以 Test 开头的类中的 test_ 开头的方法
- 以 test_ 开头的函数
3.2 运行测试
# 运行所有测试
pytest
# 运行特定文件
pytest test_sample.py
# 运行特定类
pytest test_sample.py::TestMathOperations
# 运行特定测试
pytest test_sample.py::test_addition
# 显示详细输出
pytest -v
# 显示打印输出
pytest -s
# 在第一次失败后停止
pytest -x
# 运行上次失败的测试
pytest --lf
# 运行带有特定标记的测试
pytest -m marker_name
4.夹具(Fixtures)
pytest的fixture比unittest的setUp/tearDown更灵活
4.1 基本fixture
scope,使用function和class时,会调用2次
import pytest
@pytest.fixture(scope="function") # 默认,每个测试函数执行一次
# @pytest.fixture(scope="class") # 每个测试类执行一次
# @pytest.fixture(scope="module") # 每个模块执行一次
# @pytest.fixture(scope="session") # 整个测试会话执行一次
def sample_data():
data=[1,2,3,4,5]
print('sample_data--》提供数据')
yield data # 提供测数据给测试
def test_data_length(sample_data):
assert len(sample_data)==5
5.参数化测试
装饰器里也写明了三个参数,对应后面列表里的元组数据
@pytest.mark.parametrize("a,b,expected",[(1,2,3),(-1,1,0)])
def test_addition(a,b,expected):
assert a+b==expected
6.标记(Markers)
@pytest.mark.skip
def test_add_000():
assert False
@pytest.mark.skipif(reason="功能未实现")
def test_add_001():
assert False
@pytest.mark.xfail # 预期失败
def test_add_002():
assert 3 + 2 == 4
main.py::test_add_000 SKIPPED (unconditional skip) [ 60%]
main.py::test_add_001 SKIPPED (功能未实现) [ 80%]
main.py::test_add_002 XFAIL
返回值分别对三个函数方法做了解释,用于跳过测试
7.插件系统
# 安装常用插件 pip install pytest-cov
# 测试覆盖率 pip install pytest-xdist
# 并行测试 pip install pytest-mock
# 更好的 mock 支持
8.项目结构
project/
----my_package
----__init__.py
----module.py
----tests
----__init__.py
----test_module.py
__init__.py
执行并生成测试用例
pytest_project/
├── my_package/ # 被测代码文件夹
│ └── module.py # 包含需要测试的函数
├── tests/ # 测试代码文件夹
│ └── test_module.py # 测试用例
└── main.py # 主运行文件
import pytest
if __name__=="__main__":
pytest.main()
问题:这么写,它怎么知道测试代码在哪里?
答案:新建一个pytest.ini文件,在配置文件中,填写如下,获取指定文件夹下的所有py文件,这样会生成一条固定报告文件
[pytest]
python_files = pytest_project/tests/test_*.py # 默认匹配当前目录的文件
addopts = --html=report.html -v
问题2:如果需要修改报告名称要怎么做?
答案2:新建conftest.py文件,通过钩子函数,动态调整报告名称
import pytest
from datetime import datetime
import os
def pytest_configure(config):
# 动态生成报告路径(如带时间戳)
timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
report_dir = "test_reports"
report_name = f"report_{timestamp}.html"
os.makedirs(report_dir, exist_ok=True)
config.option.htmlpath = os.path.join(report_dir, report_name)