Python-模块篇(测试工具篇、unittest、pytest)
1、测试框架-unittest
unittest是Python 标准库自带的单元测试框架,提供基础功能,适合简单测试。
- TestFixture:准备\还原测试环境,比如setUp()、tearDow()
- TestCase:测试用例
- TestSuite:测试套件,用于组合多个测试用例
- TestLoader:发现和加载测试用例
- TestRunner:运行测试并输出结果(TextTestRunner输出纯文本,HTMLTestRunner输出HTML文件)
- 基础用法示例:
import unittest #必须继承unittest.TestCase class TestMath(unittest.TestCase): # 测试前置:每个测试方法执行前运行 def setUp(self): self.a = 3 self.b = 5 # 测试后置:每个测试方法执行后运行 def tearDown(self): pass #测试方法必须以"test_"开头 def test_addition(self): self.assertEqual(self.a + self.b, 8) #是否相等 #其它断言:assertTrue(x)、assertIs(a, b)、assertIn(a, b) def test_division_by_zero(self): with self.assertRaises(ZeroDivisionError): #是否抛出指定异常 self.a / 0 @classmethod def setUpClass(cls): """整个测试类执行前运行一次""" print("测试类开始") @classmethod def tearDownClass(cls): """整个测试类执行后运行一次""" print("测试类结束") if __name__ == "__main__": # 会运行当前文件中所有以 test_ 开头的方法 unittest.main()
2、测试框架-pytest(pip install pytest)
pytest 是在 unittest 的基础上发展而来的,语法更简洁、功能更丰富。
|
基本规则 文件名:test_*.py 或 *_test.py 函数名:test_* 类名:Test*(类中方法也需以 test_ 开头) |
断言 assert result == 8 assert flag is True assert item in list pytest.raises() #否抛出预期异常 其它 @pytest.mark.slow: 标记与分组 @pytest.mark.flaky(reruns=5, reruns_delay=2):失败重试5次
|
|
import pytest # 1. 默认Fixture:提供测试数据(每次依赖都会重新执行一次,返回全新对象) @pytest.fixture def sample_data(): return {"name": "Alice", "age": 30} def test_fixture_basic(sample_data): #使用fixture:直接在测试函数参数中注入 assert sample_data["name"] == "Alice" assert sample_data["age"] == 30 # 2. Fixture带清理(使用yield) @pytest.fixture def db_connection(): print("\n[前置] 连接数据库") conn = {"host": "localhost", "status": "connected"} yield conn # 返回资源给测试函数 print("\n[后置] 关闭数据库连接") #测试完成后再执行 def test_db(db_connection): assert db_connection["status"] == "connected" # 3. Fixture作用域(scope) @pytest.fixture(scope="module") # module: 整个模块只执行一次 def module_scope_data(): print("\n[module] 只执行一次") return {"key": "shared"} def test_module_scope_1(module_scope_data): print("测试1:", module_scope_data) def test_module_scope_2(module_scope_data): print("测试2:", module_scope_data) # 4. 使用多个Fixture @pytest.fixture def user(): return {"id": 1, "name": "Bob"} @pytest.fixture def user_with_age(user): user["age"] = 25 return user def test_multi_fixtures(user_with_age): assert user_with_age["name"] == "Bob" assert user_with_age["age"] == 25 # 5. 自动使用Fixture(无需在参数中声明、每个测试函数运行前自动执行) @pytest.fixture(autouse=True) def auto_log(request): #使用request.node.name获取测试函数的名字 print(f"\n开始执行测试: {request.node.name}") def test_autouse(): print("最后的测试") |
@pytest.mark.parametrize:参数化 import pytest # 用一组数据运行同一个测试 @pytest.mark.parametrize("input_value, expected", [ (1, 2), (2, 3), (3, 4), ]) def test_increment(input_value, expected): #传入参数名使用 assert input_value + 1 == expected # 组合参数(笛卡尔积) @pytest.mark.parametrize("x", [1, 2])
|
|
跳过与预期失败 import pytest import sys # 1. 无条件跳过 @pytest.mark.skip(reason="此功能尚未实现") def test_not_ready(): pass # 2. 条件跳过 @pytest.mark.skipif(sys.version_info < (3, 8), reason="需要Python 3.8+") def test_python_version(): assert True # 3. 预期失败(bug已知,先标记) @pytest.mark.xfail(reason="已知Bug #123,尚未修复") def test_known_bug(): assert 1 == 2 # 这个断言会失败,但pytest不会将其计为失败 # 4. 条件预期失败 @pytest.mark.xfail(sys.platform == "win32", reason="Windows上不支持") def test_windows_only(): assert True """ |
命令行常用参数 pytest #运行所有测试 pytest test_file.py #运行指定文件 pytest test_file.py::test_func #运行指定测试函数 pytest -v #详细输出 pytest -s #显示print输出(不捕获) pytest -x #遇到第一个失败就停止 pytest --maxfail=3 #遇到第3次失败后停止 pytest -m "slow" #运行带smoke标记的测试 pytest -k "login" #运行名称包含"login"的测试 pytest --pdb #失败时进入调试器 pytest --html=report.html #生成HTML报告(需安装pytest-html) pytest --cov=my_module #生成覆盖率报告(需安装pytest-cov) pytest --reruns 3 --reruns-delay 1 #失败后重跑3次,每次重跑前等待1秒(安装pytest-rerunfailures) pytest-xdist #并行执行测试插件
|
本文来自博客园,作者:FengweiTech,转载请注明原文链接:https://www.cnblogs.com/fengwei-blogs/p/21300178

浙公网安备 33010602011771号