单元测试 #

一、unittest模块 #

python
import unittest

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

class TestAdd(unittest.TestCase):
    def test_add_positive(self):
        self.assertEqual(add(2, 3), 5)
    
    def test_add_negative(self):
        self.assertEqual(add(-1, -1), -2)
    
    def test_add_zero(self):
        self.assertEqual(add(0, 0), 0)

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

二、断言方法 #

python
import unittest

class TestAssertions(unittest.TestCase):
    def test_equal(self):
        self.assertEqual(1 + 1, 2)
    
    def test_not_equal(self):
        self.assertNotEqual(1, 2)
    
    def test_true(self):
        self.assertTrue(True)
    
    def test_false(self):
        self.assertFalse(False)
    
    def test_in(self):
        self.assertIn(1, [1, 2, 3])
    
    def test_is(self):
        a = None
        self.assertIsNone(a)
    
    def test_raises(self):
        with self.assertRaises(ValueError):
            int("invalid")

三、测试夹具 #

python
import unittest

class TestDatabase(unittest.TestCase):
    def setUp(self):
        """每个测试前执行"""
        self.db = connect_database()
    
    def tearDown(self):
        """每个测试后执行"""
        self.db.close()
    
    @classmethod
    def setUpClass(cls):
        """所有测试前执行一次"""
        cls.shared_resource = setup_resource()
    
    @classmethod
    def tearDownClass(cls):
        """所有测试后执行一次"""
        cleanup_resource()
    
    def test_query(self):
        result = self.db.query("SELECT 1")
        self.assertIsNotNone(result)

四、pytest框架 #

python
# test_module.py

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

def test_add_positive():
    assert add(2, 3) == 5

def test_add_negative():
    assert add(-1, -1) == -2

def test_add_zero():
    assert add(0, 0) == 0

五、pytest夹具 #

python
import pytest

@pytest.fixture
def database():
    db = connect_database()
    yield db
    db.close()

def test_query(database):
    result = database.query("SELECT 1")
    assert result is not None

六、pytest参数化 #

python
import pytest

@pytest.mark.parametrize("a,b,expected", [
    (1, 2, 3),
    (2, 3, 5),
    (0, 0, 0),
    (-1, 1, 0),
])
def test_add(a, b, expected):
    assert add(a, b) == expected

七、pytest跳过测试 #

python
import pytest
import sys

@pytest.mark.skip(reason="暂时跳过")
def test_something():
    pass

@pytest.mark.skipif(sys.version_info < (3, 8), reason="需要Python 3.8+")
def test_new_feature():
    pass

@pytest.mark.xfail(reason="已知失败")
def test_expected_failure():
    assert False

八、运行测试 #

bash
# unittest
python -m unittest test_module.py
python -m unittest discover

# pytest
pytest test_module.py
pytest tests/
pytest -v  # 详细输出
pytest -k "add"  # 运行匹配的测试
pytest -x  # 第一次失败就停止
pytest --cov  # 代码覆盖率

九、最佳实践 #

python
# 1. 测试文件命名:test_*.py 或 *_test.py
# 2. 测试函数命名:test_*
# 3. 测试类命名:Test*
# 4. 每个测试只测试一个功能
# 5. 使用描述性的测试名称

def test_add_should_return_sum_of_two_numbers():
    assert add(2, 3) == 5

def test_add_should_handle_negative_numbers():
    assert add(-1, -2) == -3
最后更新:2026-03-16