DevCN
菜单
全部文章快讯开发科技深度热点

Python 单元测试:用 unittest 检查时长解析的正常与边界输入

为学习时长解析函数编写表驱动测试,覆盖合法输入、边界、格式错误和类型错误,掌握 subTest 与 assertRaises 的使用方法。


本节目标

为学习时长解析函数编写表驱动测试,覆盖合法输入、边界、格式错误和类型错误,掌握 subTest 与 assertRaises 的使用方法。

知识与使用场景

前面的示例通过观察终端输出验证功能。单元测试把预期写成可重复执行的检查,代码修改后可以再次运行,确认契约没有被意外破坏。本节复制时长解析函数到同一文件,保证初次练习不依赖其他章节的文件位置。

测试分成三组:可解析的文本、应拒绝的文本、不符合输入类型的对象。对每组多个输入使用 subTest,让失败报告包含具体值。断言异常类型能检查失败方式,而不只是检查程序有没有输出一行文字。

测试重点是对外行为:返回多少分钟、哪些输入被拒绝。不要让测试照抄函数内部每一步,也不要为凑覆盖率只测试同一个普通数字。0、1440、负数和刚超过上限更能揭示边界判断错误。

完整示例

import unittest


def parse_minutes(text):
    if not isinstance(text, str):
        raise TypeError("时长必须以文本提供")
    try:
        value = int(text.strip())
    except ValueError as exc:
        raise ValueError("时长必须是整数文本") from exc
    if not 0 <= value <= 1440:
        raise ValueError("时长必须在0到1440之间")
    return value


class ParseMinutesTests(unittest.TestCase):
    def test_valid(self):
        for raw, expected in [("0", 0), (" 45 ", 45), ("1440", 1440)]:
            with self.subTest(raw=raw):
                self.assertEqual(parse_minutes(raw), expected)

    def test_invalid_text(self):
        for raw in ["", "12.5", "-1", "1441"]:
            with self.subTest(raw=raw):
                with self.assertRaises(ValueError):
                    parse_minutes(raw)

    def test_invalid_type(self):
        for raw in [None, 20, True]:
            with self.subTest(raw=raw):
                with self.assertRaises(TypeError):
                    parse_minutes(raw)


if __name__ == "__main__":
    unittest.main(verbosity=2)

预期结果

OK

运行与逐步理解

保存为 test_minutes.py。使用选定的解释器运行 test_minutes.py,或在同目录运行 python -m unittest -v test_minutes,其中 python 应替换为自己的虚拟环境解释器路径。

执行器会运行三个 test 开头的方法,内部合计检查 10 组输入。正常结果包含各方法的 ok、Ran 3 tests 和末尾 OK,耗时与模块前缀会因运行方式不同而变化。不要误把 10 组输入当成报告必须显示的 10 个测试方法。

真实项目可将 parse_minutes 放到 minutes.py,再由测试文件 from minutes import parse_minutes。保持导入时没有交互输入或文件写入,测试才容易自动执行。输出到标准错误流是 unittest 的常见行为,不等于测试失败,应同时看退出码和测试结果。

常见问题与边界

  • assertRaises 必须围住实际调用,不能只传一个已计算好的返回值。
  • 测试文件不要命名为 unittest.py,否则可能遮蔽标准库。
  • 全部通过只能说明已覆盖场景满足预期,不代表任意输入都正确。
  • 测试要能发现错误;可以临时把范围上限改成 1439,确认 1440 用例失败后再恢复。

动手练习

给有效输入增加 " +30 ",给无效文本增加 "1440.0",运行后说明结果;临时把下限比较改成 0 < value 再运行。

参考答案

带正号和空白的整数文本按当前契约应返回 30;1440.0 含小数点,应抛 ValueError。把下限改为严格大于零后,"0" 子用例失败,说明测试确实保护了合法边界。验证后恢复原实现再提交。

下载推广海报

文章推广海报

《Python 单元测试:用 unittest 检查时长解析的正常与边界输入》完整推广海报
DISCUSSION

文章回复

0 条公开回复
未登录回复需要审核后公开
还没有回复,欢迎参与讨论。