什么是单元测试?

单元测试 是指对软件中的某个功能模块(通常是一个函数或方法)进行测试,确保它在各种输入条件下能够返回预期的结果。每个单元测试通常只测试代码的一小部分,并且独立于其他部分的代码。

单元测试的目标是确保每个功能模块独立且正确地执行它们的任务,从而帮助开发人员快速定位和修复潜在的问题。

Python 中的 unittest 模块

Python 提供了内置的单元测试框架 unittest,这是一个标准库模块,用来编写和运行测试用例。unittest 提供了类似于 Java 中 JUnit 的功能,它支持以下功能:

  • 定义测试用例类
  • 编写多个测试方法
  • 设置和清理测试环境
  • 断言测试结果
  • 自动化运行测试

基本示例:编写一个简单的单元测试

首先,让我们通过一个简单的示例来了解如何使用 unittest 编写单元测试。假设我们有一个简单的函数 add(),用于计算两个数的和:

def add(a, b):
    return a + b

我们可以为这个函数编写以下测试用例:

import unittest

# 测试用例类
class TestAddFunction(unittest.TestCase):
    
    # 编写测试方法
    def test_add_positive_numbers(self):
        self.assertEqual(add(2, 3), 5)  # 测试两个正数的和
    
    def test_add_negative_numbers(self):
        self.assertEqual(add(-1, -1), -2)  # 测试两个负数的和

    def test_add_zero(self):
        self.assertEqual(add(0, 0), 0)  # 测试两个零相加

# 运行测试
if __name__ == '__main__':
    unittest.main()

在这个测试用例中,我们定义了一个继承自 unittest.TestCase 的类 TestAddFunction,并编写了三个测试方法来验证 add() 函数在不同输入下的表现。

  • self.assertEqual(a, b) 是一个 断言方法,用来验证 a 和 b 是否相等。如果不相等,测试就会失败。

运行这个脚本后,unittest 框架会自动执行所有以 test_ 开头的测试方法,并给出测试结果。如果所有测试通过,你将看到如下输出:

...
----------------------------------------------------------------------
Ran 3 tests in 0.000s

OK

断言方法

unittest 提供了多种断言方法来验证测试结果的正确性。常见的断言方法包括:

  • assertEqual(a, b):验证 a == b
  • assertNotEqual(a, b):验证 a != b
  • assertTrue(x):验证 x 为 True
  • assertFalse(x):验证 x 为 False
  • assertIsNone(x):验证 x is None
  • assertIsNotNone(x):验证 x is not None
  • assertIn(a, b):验证 a 在 b 中
  • assertRaises(Error):验证是否抛出了指定的异常
def divide(a, b):
    if b == 0:
        raise ValueError("Division by zero!")
    return a / b

class TestDivideFunction(unittest.TestCase):
    def test_divide_by_zero(self):
        with self.assertRaises(ValueError):
            divide(10, 0)

设置与清理:setUp() 与 tearDown()

在测试中,有时我们需要在每个测试方法之前进行一些预处理,或者在测试结束后清理资源。unittest 提供了 setUp() 和 tearDown() 方法来实现这些需求。

  • setUp():在每个测试方法之前运行,用于准备测试环境。
  • tearDown():在每个测试方法之后运行,用于清理资源。
class TestWithSetup(unittest.TestCase):
    
    def setUp(self):
        self.num1 = 10
        self.num2 = 20
    
    def tearDown(self):
        print("Test completed.")

    def test_addition(self):
        self.assertEqual(self.num1 + self.num2, 30)

if __name__ == '__main__':
    unittest.main()

跳过测试与预期失败

在某些情况下,某些测试暂时不需要运行,或者我们希望测试在某些条件下会失败。unittest 提供了 @unittest.skip 和 @unittest.expectedFailure 装饰器来实现这些功能。

  • @unittest.skip(reason):跳过该测试,并给出跳过的原因。
  • @unittest.expectedFailure:标记为预期失败的测试,即使失败也不会标记为错误。
class TestSkipping(unittest.TestCase):
    
    @unittest.skip("Skipping this test")
    def test_skipped(self):
        self.assertEqual(1, 1)
    
    @unittest.expectedFailure
    def test_expected_failure(self):
        self.assertEqual(1, 2)

if __name__ == '__main__':
    unittest.main()

Logo

GitCode 天启AI是一款由 GitCode 团队打造的智能助手,基于先进的LLM(大语言模型)与多智能体 Agent 技术构建,致力于为用户提供高效、智能、多模态的创作与开发支持。它不仅支持自然语言对话,还具备处理文件、生成 PPT、撰写分析报告、开发 Web 应用等多项能力,真正做到“一句话,让 Al帮你完成复杂任务”。

更多推荐