news 2026/4/22 19:35:41

Python提高: unittest和 pytest的使用方法-由Deepseek产生

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Python提高: unittest和 pytest的使用方法-由Deepseek产生

以下分别给出unittestpytest的详细案例,包含常见测试场景:基本断言、异常测试、夹具、模拟、参数化、跳过/预期失败。

1. 被测试代码 (待测模块calculator.py)

# calculator.pyimportrequestsclassCalculator:defadd(self,a,b):returna+bdefdivide(self,a,b):ifb==0:raiseValueError("除数不能为零")returna/bdeffetch_data(url):"""模拟网络请求,返回状态码和JSON"""resp=requests.get(url)returnresp.status_code,resp.json()

2. unittest 详细案例

# test_unittest_demo.pyimportunittestfromunittest.mockimportpatch,MockfromcalculatorimportCalculator,fetch_dataclassTestCalculator(unittest.TestCase):"""基本测试 + 夹具 + 模拟 + 参数化 + 跳过"""@classmethoddefsetUpClass(cls):"""所有测试运行前执行一次"""print("\n[setUpClass] 初始化计算器实例")cls.calc=Calculator()@classmethoddeftearDownClass(cls):"""所有测试运行后执行一次"""print("[tearDownClass] 清理资源")defsetUp(self):"""每个测试方法前执行"""print(f"\n[setUp] 准备测试:{self._testMethodName}")deftearDown(self):"""每个测试方法后执行"""print(f"[tearDown] 完成测试:{self._testMethodName}")# ---------- 基本断言 ----------deftest_add_positive(self):self.assertEqual(self.calc.add(2,3),5)self.assertAlmostEqual(self.calc.add(0.1,0.2),0.3,places=6)deftest_divide_normal(self):self.assertEqual(self.calc.divide(10,2),5.0)# ---------- 异常测试 ----------deftest_divide_by_zero(self):withself.assertRaises(ValueError)asctx:self.calc.divide(5,0)self.assertEqual(str(ctx.exception),"除数不能为零")# ---------- 模拟 (mock) ----------@patch('calculator.requests.get')deftest_fetch_data_success(self,mock_get):# 配置模拟对象mock_response=Mock()mock_response.status_code=200mock_response.json.return_value={"key":"value"}mock_get.return_value=mock_response status,data=fetch_data("http://example.com")self.assertEqual(status,200)self.assertEqual(data,{"key":"value"})mock_get.assert_called_once_with("http://example.com")@patch('calculator.requests.get')deftest_fetch_data_failure(self,mock_get):mock_response=Mock()mock_response.status_code=404mock_response.json.side_effect=Exception("Not Found")mock_get.return_value=mock_responsewithself.assertRaises(Exception):fetch_data("http://example.com/bad")# ---------- 参数化测试 (使用 subTest) ----------deftest_add_multiple_inputs(self):test_cases=[(1,2,3),(-1,-1,-2),(0,0,0),(100,-50,50)]fora,b,expectedintest_cases:withself.subTest(a=a,b=b,expected=expected):self.assertEqual(self.calc.add(a,b),expected)# ---------- 跳过测试 ----------@unittest.skip("演示跳过,该功能尚未实现")deftest_multiply_not_implemented(self):pass@unittest.skipIf(True,"条件满足时跳过")deftest_skip_conditionally(self):pass@unittest.expectedFailuredeftest_expected_failure(self):# 这个断言会失败,但不会计入失败数self.assertEqual(1,2)if__name__=='__main__':unittest.main(verbosity=2)

运行方式python test_unittest_demo.pypython -m unittest test_unittest_demo

3. pytest 详细案例

# test_pytest_demo.pyimportpytestfromunittest.mockimportMock,patchfromcalculatorimportCalculator,fetch_data# ---------- 夹具 (fixture) ----------@pytest.fixture(scope="class")defcalculator():"""类级别夹具,返回计算器实例"""print("\n[fixture] 创建计算器实例")calc=Calculator()yieldcalcprint("[fixture] 销毁计算器实例")@pytest.fixturedefsample_data():"""函数级别夹具,返回测试数据"""return{"a":10,"b":5}# ---------- 测试类 ----------classTestCalculator:"""使用类级别夹具"""deftest_add(self,calculator,sample_data):result=calculator.add(sample_data["a"],sample_data["b"])assertresult==15# pytest 使用原生 assertdeftest_divide_normal(self,calculator):assertcalculator.divide(9,3)==3.0deftest_divide_by_zero(self,calculator):withpytest.raises(ValueError,match="除数不能为零"):calculator.divide(5,0)# ---------- 参数化测试 (pytest 特色) ----------@pytest.mark.parametrize("a,b,expected",[(1,2,3),(-1,-1,-2),(0,0,0),(100,-50,50),])deftest_add_parametrized(a,b,expected):calc=Calculator()assertcalc.add(a,b)==expected# 组合参数化 + 夹具@pytest.mark.parametrize("input_val,expected",[(5,5),(0,0),(-3,-3)])deftest_identity(calculator,input_val,expected):assertcalculator.add(input_val,0)==expected# ---------- 模拟 (使用 mocker fixture,需要安装 pytest-mock) ----------# 也可以直接使用 unittest.mock,pytest 自动兼容deftest_fetch_data_success(mocker):# 使用 pytest-mock 的 mocker fixturemock_get=mocker.patch('calculator.requests.get')mock_response=Mock()mock_response.status_code=200mock_response.json.return_value={"key":"value"}mock_get.return_value=mock_response status,data=fetch_data("http://example.com")assertstatus==200assertdata=={"key":"value"}mock_get.assert_called_once_with("http://example.com")deftest_fetch_data_failure():withpatch('calculator.requests.get')asmock_get:mock_response=Mock()mock_response.status_code=404mock_response.json.side_effect=Exception("Not Found")mock_get.return_value=mock_responsewithpytest.raises(Exception):fetch_data("http://example.com/bad")# ---------- 跳过与预期失败 ----------@pytest.mark.skip(reason="演示跳过,未实现功能")deftest_skip_example():pass@pytest.mark.skipif(True,reason="条件满足时跳过")deftest_skip_conditionally():pass@pytest.mark.xfail(reason="已知问题,暂时预期失败")deftest_expected_failure():assert1==2# ---------- 临时文件与 capsys (pytest 内置 fixture) ----------deftest_capsys_example(capsys):print("Hello, world!")captured=capsys.readouterr()assertcaptured.out=="Hello, world!\n"deftest_tmp_path(tmp_path):d=tmp_path/"sub"d.mkdir()f=d/"test.txt"f.write_text("pytest rocks")assertf.read_text()=="pytest rocks"# ---------- 自定义标记 ----------@pytest.mark.slowdeftest_slow_operation():importtime time.sleep(0.1)assertTrue# 运行方式: pytest -m slow (只运行标记为 slow 的测试)

运行方式

  • 安装 pytest:pip install pytest pytest-mock
  • 执行:pytest test_pytest_demo.py -v
  • 带覆盖率:pytest --cov=calculator test_pytest_demo.py

关键差异对比

特性unittestpytest
断言风格self.assertEqual(a, b)assert a == b
夹具setUp/tearDown@pytest.fixture,更灵活
参数化subTestparameterized@pytest.mark.parametrize
模拟unittest.mockunittest.mockmocker
跳过/预期失败@unittest.skip/expectedFailure@pytest.mark.skip/xfail
插件生态较少极丰富 (xdist, cov, asyncio…)
学习曲线较低,但代码冗长稍高,但更简洁强大

建议:新项目直接选择pytest,旧项目维护可使用 unittest。两者可混合使用(pytest 能运行 unittest 风格的测试)。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/4/22 20:27:24

Kotaemon新手入门:3步搞定智能文档问答系统搭建

Kotaemon新手入门:3步搞定智能文档问答系统搭建 你是不是经常面对一堆文档资料,想快速找到某个问题的答案,却要花大量时间翻找?或者你正在开发一个客服系统,需要让AI能准确回答用户关于产品文档的问题?如果…

作者头像 李华
网站建设 2026/4/23 6:04:41

金属-半导体接触实战指南:如何用Multisim仿真肖特基二极管特性曲线

金属-半导体接触实战指南:Multisim仿真肖特基二极管特性曲线全解析 在电子设计领域,肖特基二极管凭借其低正向压降和快速开关特性,已成为高频整流、射频混频等应用的首选元件。与传统的PN结二极管不同,肖特基二极管基于金属-半导…

作者头像 李华
网站建设 2026/4/23 3:26:13

避开这些坑:S32K3 Safety功能开发中常见的5个误区与调试实战

S32K3安全功能开发实战:5个关键误区与深度调试指南 在汽车电子领域,功能安全开发从来不是纸上谈兵。当工程师第一次接触S32K3系列MCU的安全功能时,往往会被其丰富的硬件机制和复杂的软件框架所震撼——锁步核、ECC校验、MPU/XRDC访问控制、EI…

作者头像 李华
网站建设 2026/4/22 18:43:36

告别混乱布线:单网口软路由+交换机VLAN方案,打造简洁家庭网络中枢

单网口软路由VLAN交换机:极简家庭网络架构实战指南 现代家庭网络设备越来越多,从智能电视到NAS存储,从安防摄像头到物联网设备,传统的路由器交换机组网方式往往导致弱电箱拥挤不堪。本文将介绍如何利用单网口设备和VLAN技术&#…

作者头像 李华