Day 34:【99天精通Python】单元测试 (Unittest) - 给代码上个保险

Day 34:【99天精通Python】单元测试 (Unittest) - 给代码上个保险

前言

欢迎来到第34天!

在之前的开发中,我们通常是怎么验证代码对不对的?
—— 写完代码,手动运行一下,输入几个参数,看看打印结果对不对。
这种人工测试方式在小脚本里还行,但当项目变大时:

  1. 效率低:每次改个小功能,都要把所有功能手动测一遍,累死人。
  2. 不可靠:人是会犯错的,容易漏测某些边界情况(比如除以0、空输入)。
  3. 不敢重构:想优化代码,又怕改坏了以前的功能,导致不敢动。

单元测试 (Unit Testing)就是为了解决这些问题。我们写一段代码(测试脚本)来专门检测另一段代码(业务逻辑)。一旦业务代码被修改,只需一键运行测试脚本,几秒钟就能知道有没有把旧功能改坏。

本节内容:

  • 什么是单元测试?
  • Python 内置模块unittest
  • 常用断言方法 (assertEqual,assertTrue…)
  • 测试固件:setUptearDown
  • 实战练习:为银行账户类编写测试

一、第一个测试用例

假设我们有一个简单的函数add(a, b)

# math_func.pydefadd(a,b):returna+b

我们想测试它对不对。使用unittest模块:

# test_math.pyimportunittestfrommath_funcimportadd# 1. 定义一个测试类,必须继承 unittest.TestCaseclassTestMathFunc(unittest.TestCase):# 2. 定义测试方法,必须以 test_ 开头deftest_add_integers(self):"""测试整数相加"""result=add(1,2)# 3. 断言:判断 result 是否等于 3self.assertEqual(result,3)deftest_add_strings(self):"""测试字符串相加"""result=add("hello"," world")self.assertEqual(result,"hello world")# 4. 运行测试if__name__=='__main__':unittest.main()

运行test_math.py,如果一切正常,控制台会显示OK。如果把add函数改成return a - b,运行测试就会报错FAIL


二、常用断言 (Assertions)

断言是测试的核心,用来判断"实际结果"与"预期结果"是否一致。

方法检查内容
assertEqual(a, b)a == b
assertNotEqual(a, b)a != b
assertTrue(x)x为真
assertFalse(x)x为假
assertIn(item, container)item在容器中
assertIsNone(x)x是 None
assertRaises(Error, func)func执行时抛出指定异常

示例:测试除法异常

defdivide(a,b):ifb==0:raiseValueError("除数不能为0")returna/bclassTestDivide(unittest.TestCase):deftest_divide_zero(self):# 断言:执行 divide(10, 0) 时应该抛出 ValueErrorwithself.assertRaises(ValueError):divide(10,0)

三、测试固件:setUp 与 tearDown

有时候,每个测试用例运行前都需要做一些准备工作(比如连接数据库、创建临时文件),运行后需要清理(断开连接、删除文件)。
这时就用到setUp(前置)和tearDown(后置)。

  • setUp(): 每个test_方法运行自动执行。
  • tearDown(): 每个test_方法运行自动执行。
classTestDatabase(unittest.TestCase):defsetUp(self):print("\n--- 连接数据库 ---")self.db={"user":"admin"}# 模拟数据库连接deftearDown(self):print("--- 断开连接 ---")self.db=Nonedeftest_query(self):print("执行查询测试")self.assertEqual(self.db["user"],"admin")deftest_update(self):print("执行更新测试")self.db["user"]="root"self.assertEqual(self.db["user"],"root")

执行顺序

  1. setUp->test_query->tearDown
  2. setUp->test_update->tearDown

注意:每个测试用例之间是相互独立的。test_update修改了数据,不会影响test_query(因为它在下一次运行时会重新setUp)。


四、实战练习:测试银行账户类

回顾一下 Day 14 写的BankAccount类,我们给它加上单元测试。

业务代码 (bank.py)

classBankAccount:def__init__(self,balance=0):self.balance=balancedefdeposit(self,amount):ifamount<=0:raiseValueError("存款金额必须大于0")self.balance+=amountreturnself.balancedefwithdraw(self,amount):ifamount>self.balance:raiseValueError("余额不足")self.balance-=amountreturnself.balance

测试代码 (test_bank.py)

importunittestfrombankimportBankAccountclassTestBankAccount(unittest.TestCase):defsetUp(self):# 每次测试前,都创建一个初始余额为 100 的账户self.account=BankAccount(100)deftest_deposit(self):"""测试存款正常"""new_balance=self.account.deposit(50)self.assertEqual(new_balance,150)self.assertEqual(self.account.balance,150)deftest_deposit_negative(self):"""测试存负数报错"""withself.assertRaises(ValueError):self.account.deposit(-10)deftest_withdraw(self):"""测试取款正常"""self.account.withdraw(30)self.assertEqual(self.account.balance,70)deftest_withdraw_overdraft(self):"""测试透支报错"""withself.assertRaises(ValueError):self.account.withdraw(200)if__name__=='__main__':unittest.main()

五、如何运行测试

5.1 命令行运行

在终端中,不需要修改代码,直接运行:

# 运行指定文件python -m unittest test_bank.py# 自动发现并运行当前目录下所有 test_*.py 文件python -m unittest discover

5.2 生成测试报告

虽然unittest自带的输出很简单,但我们可以配合第三方库(如HTMLTestRunner,不过现在更流行用pytest)来生成漂亮的 HTML 报告。我们会在进阶课程的最后介绍更强大的pytest框架。现在先掌握unittest的基础。


六、常见问题

Q1:为什么我的测试方法没运行?

请检查方法名是否以test_开头。如果写成def check_add(self):unittest会忽略它。

Q2:测试代码和业务代码应该放在一起吗?

不建议。通常在项目根目录下创建一个tests/文件夹,专门存放测试脚本。

Q3:unittestpytest哪个好?

  • unittest:Python 内置,不需要安装,符合 xUnit 标准(类、setUp/tearDown),适合学习原理。
  • pytest:第三方库,语法更简单(不需要写类,直接写 assert),插件丰富。实际工作中推荐用 pytest,但它是建立在对测试原理理解的基础上的。

七、小结

单元测试 unittest

TestCase 类

断言方法

生命周期

继承 unittest.TestCase

方法名必须以 test_ 开头

assertEqual (相等)

assertTrue (真)

assertRaises (异常)

setUp() (每例开始前)

test_xxx() (运行测试)

tearDown() (每例结束后)

关键要点

  1. 测试是保险:它保证了你的代码在修改后依然符合预期。
  2. 独立性:每个测试用例应该是独立的,互不干扰。
  3. 覆盖率:不仅要测"正常情况",更要测"异常情况"(如存负数、取款透支)。

八、课后作业

  1. 字符串工具测试:编写一个函数is_palindrome(s)判断字符串是否为回文(如 “aba”)。编写测试用例,覆盖:回文串、非回文串、空字符串、含空格的字符串。
  2. 购物车测试:为 Day 16 的Cart类编写测试。测试功能:add添加商品,len计算数量,以及确保添加重复商品时逻辑是否符合预期(假设允许重复)。
  3. 修复 Bug:在练习1中,如果输入的字符串包含大小写(如 “Racecar”),你的函数能正确判断吗?编写一个失败的测试用例,然后修改原函数代码,直到测试通过。

下节预告

Day 35:综合实战 - 爬虫与数据分析可视化(上)- 进阶篇的理论知识学得差不多了。接下来的几天,我们将做一个真·实战项目:爬取真实的网站数据,存入数据库,并生成精美的图表!


系列导航

  • 上一篇:Day 33 - 日志记录Logging
  • 下一篇:Day 35 - 综合实战爬虫与可视化上(待更新)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/1155998.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Day 35:【99天精通Python】综合实战 - 爬虫与数据分析可视化(上) - 数据采集与入库

Day 35&#xff1a;【99天精通Python】综合实战 - 爬虫与数据分析可视化(上) - 数据采集与入库 前言 欢迎来到第35天&#xff01; 经过前两周的学习&#xff0c;我们已经掌握了网络请求&#xff08;Requests&#xff09;、网页解析&#xff08;BeautifulSoup&#xff09;、数…

多FDCAN接口同步配置实战:双通道并行通信实现

多FDCAN接口实战&#xff1a;双通道并行通信如何突破带宽瓶颈你有没有遇到过这样的情况&#xff1f;在开发一个高实时性的车载控制模块时&#xff0c;CAN总线突然“卡顿”——数据延迟飙升、报文丢失频发。排查一圈后发现&#xff0c;并不是硬件故障&#xff0c;而是单条CAN通道…

强烈安利10个AI论文软件,MBA毕业论文轻松搞定!

强烈安利10个AI论文软件&#xff0c;MBA毕业论文轻松搞定&#xff01; AI 工具如何让论文写作更高效&#xff1f; 在当前的学术环境中&#xff0c;MBA 学生和研究者们正面临越来越多的挑战。从选题到撰写&#xff0c;再到查重与修改&#xff0c;每一个环节都可能成为耗时费力的…

Figma中文界面本地化:设计师专属的语言解决方案

Figma中文界面本地化&#xff1a;设计师专属的语言解决方案 【免费下载链接】figmaCN 中文 Figma 插件&#xff0c;设计师人工翻译校验 项目地址: https://gitcode.com/gh_mirrors/fi/figmaCN 语言障碍的痛点与解决方案 对于国内设计从业者而言&#xff0c;Figma作为专…

Day 36:【99天精通Python】综合实战 - 爬虫与数据分析可视化(下) - 让数据“说话“

Day 36&#xff1a;【99天精通Python】综合实战 - 爬虫与数据分析可视化(下) - 让数据"说话" 前言 欢迎来到第36天&#xff01; 在昨天&#xff08;Day 35&#xff09;的课程中&#xff0c;我们化身为"数据采集员"&#xff0c;成功编写爬虫抓取了豆瓣 Top2…

导师推荐!8个AI论文平台测评:研究生开题报告全攻略

导师推荐&#xff01;8个AI论文平台测评&#xff1a;研究生开题报告全攻略 学术写作工具测评&#xff1a;为什么需要一份精准的AI论文平台榜单 在研究生阶段&#xff0c;开题报告和论文撰写是科研工作的核心环节&#xff0c;而高效、专业的写作工具能显著提升研究效率与成果质…

Intel平台嵌入式SPI通信:新手教程

Intel平台嵌入式SPI通信&#xff1a;从零理解eSPI的实战指南你有没有遇到过这样的情况&#xff1f;在调试一块工业主板时&#xff0c;发现电源键按下后系统无法唤醒&#xff1b;或者在做低功耗设计时&#xff0c;明明进入了S3睡眠&#xff0c;传感器数据却断了传输。这些问题的…

Doris与Trino集成:统一SQL大数据查询引擎

Doris与Trino集成:统一SQL大数据查询引擎 关键词:Doris、Trino、SQL查询引擎、大数据分析、数据仓库、联邦查询、OLAP 摘要:本文深入探讨了Apache Doris与Trino两大流行SQL查询引擎的集成方案,旨在构建统一的大数据查询平台。文章首先分析了两者的架构特点和互补优势,然后…

Day 38:【99天精通Python】线程池与进程池 - 优雅地管理并发

Day 38&#xff1a;【99天精通Python】线程池与进程池 - 优雅地管理并发 前言 欢迎来到第38天&#xff01; 在 Day 24 和 Day 25 中&#xff0c;我们学习了如何手动创建线程 (threading.Thread) 和进程 (multiprocessing.Process)。虽然原理都懂了&#xff0c;但在实际工程中&a…

“死了么”App爆火,我发现了个安卓版,代码开源!

最近看到一个特别搞笑的评论&#xff1a; 当代年轻人日常&#xff1a;用「饿了么」填饱肚子&#xff0c;「死了么」证明还活着 &#x1f602; 随着前几天「死了么」APP 爆火&#xff0c;网上的段子手们就没停下来过&#xff0c;哈哈哈哈哈 iPhone版 「死了么」是iPhone手机上…

Figma中文插件完全配置指南:告别英文界面困扰

Figma中文插件完全配置指南&#xff1a;告别英文界面困扰 【免费下载链接】figmaCN 中文 Figma 插件&#xff0c;设计师人工翻译校验 项目地址: https://gitcode.com/gh_mirrors/fi/figmaCN 还在为Figma复杂的英文界面而头疼吗&#xff1f;面对专业设计工具&#xff0c;…

基于YOLOv8的小麦田间病害识别项目|完整源码数据集+PyQt5界面+完整训练流程+开箱即用!

基于YOLOv8的小麦田间病害识别项目&#xff5c;完整源码数据集PyQt5界面完整训练流程开箱即用&#xff01; 源码包含&#xff1a;完整YOLOv8训练代码数据集(带标注)权重文件直接可允许检测的yolo检测程序直接部署教程/训练教程 基本功能演示 源码在文末哔哩哔哩视频简介处获…

基于Simulink的混合PO与INC切换MPPT策略仿真

目录 手把手教你学Simulink 一、引言&#xff1a;为什么需要“混合P&O与INC”&#xff1f; 二、系统整体架构 控制流程&#xff1a; 三、核心算法详解 1. P&O 算法&#xff08;扰动观察法&#xff09; 2. INC 算法&#xff08;电导增量法&#xff09; 3. 光照突…

多语言界面在screen中的实现:项目应用

用 GNU Screen 构建轻量级多语言终端界面&#xff1a;从原理到实战你有没有遇到过这样的场景&#xff1f;一位中国工程师深夜远程连接非洲基站的工控设备&#xff0c;刚准备执行配置命令时断网了。几小时后重新登录&#xff0c;发现之前的调试流程全中断了——日志没了、上下文…

学长亲荐8个一键生成论文工具,专科生毕业论文必备!

学长亲荐8个一键生成论文工具&#xff0c;专科生毕业论文必备&#xff01; AI 工具让论文写作不再难 在当前的学术环境中&#xff0c;AI 工具已经成为许多学生和研究者不可或缺的助手。尤其是对于专科生而言&#xff0c;面对繁重的毕业论文任务&#xff0c;如何高效地完成内容撰…

Figma中文界面终极解决方案:5分钟完成专业设计工具全面汉化

Figma中文界面终极解决方案&#xff1a;5分钟完成专业设计工具全面汉化 【免费下载链接】figmaCN 中文 Figma 插件&#xff0c;设计师人工翻译校验 项目地址: https://gitcode.com/gh_mirrors/fi/figmaCN 还在为Figma英文操作界面而困扰&#xff1f;想要快速掌握这款国际…

基于Simulink的多时间常数储能配置优化仿真

手把手教你学Simulink--基础储能管理场景实例&#xff1a;基于Simulink的多时间常数储能配置优化仿真 手把手教你学Simulink ——基础储能管理场景实例&#xff1a;基于Simulink的多时间常数储能配置优化仿真 一、引言&#xff1a;为什么需要“多时间常数储能”&#xff1f; …

大模型微调技术详解:从全参数微调到RLHF的演进与应用

文章系统介绍了大模型微调技术的发展历程&#xff0c;从2018年全参数微调到2023年的偏好对齐技术&#xff0c;包括特征提取、Adapter、LoRA、提示微调、指令微调等方法。分析了各种微调技术的原理、特点和适用场景&#xff0c;解释了微调为何在大模型时代取代从零训练&#xff…

大模型微调技术详解:从全参数微调到RLHF的演进与应用

文章系统介绍了大模型微调技术的发展历程&#xff0c;从2018年全参数微调到2023年的偏好对齐技术&#xff0c;包括特征提取、Adapter、LoRA、提示微调、指令微调等方法。分析了各种微调技术的原理、特点和适用场景&#xff0c;解释了微调为何在大模型时代取代从零训练&#xff…

S32DS使用手把手教程:从零实现CAN通信配置

从零开始玩转S32DS&#xff1a;手把手教你搞定S32K芯片上的CAN通信你有没有遇到过这种情况&#xff1f;项目紧急&#xff0c;要让两个ECU通过CAN总线对话&#xff0c;结果在S32DS里点来点去&#xff0c;引脚配了、时钟设了、波特率也算了一遍又一遍——可就是收不到一帧数据。调…