增量测试(Incremental Testing)
一句话总结:逐步添加模块并测试,而不是一次性测试所有模块。
🌟 快速理解
就像搭积木:
1 2 3 4 5 6 7 8 9 10 11 12
| 一次性测试(Big Bang): - 搭好所有积木 🧱🧱🧱 - 一次性测试 - 出问题难定位 ❌
增量测试(Incremental): - 先搭一块 🧱 - 测试 ✅ - 再加一块 🧱 - 测试 ✅ - 逐步搭建 - 问题容易定位 ✅
|
📌 核心概念
什么是增量测试?
增量测试:逐步添加模块并测试,每次只添加一个或少数几个模块。
增量测试 vs Big Bang测试
| 维度 |
增量测试 |
Big Bang测试 |
| 测试方式 |
逐步添加模块 |
一次性测试所有模块 |
| 问题定位 |
容易 |
困难 |
| 测试时机 |
开发过程中 |
开发完成后 |
| 风险 |
低 |
高 |
🎯 增量测试类型
1. 自顶向下增量测试(Top-Down)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40
|
def test_main_with_stubs(): """测试Main,使用桩模块""" class StubModuleA: def process(self): return "stub_result" class StubModuleB: def process(self): return "stub_result" main = Main(StubModuleA(), StubModuleB()) result = main.run() assert result is not None
def test_main_with_moduleA(): """测试Main + ModuleA""" main = Main(ModuleA(), StubModuleB()) result = main.run() assert result is not None
def test_main_with_all_modules(): """测试完整系统""" main = Main(ModuleA(), ModuleB()) result = main.run() assert result is not None
|
2. 自底向上增量测试(Bottom-Up)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
|
def test_moduleA1(): """测试ModuleA1""" module = ModuleA1() result = module.process() assert result == "expected"
def test_moduleA2(): """测试ModuleA2""" module = ModuleA2() result = module.process() assert result == "expected"
def test_moduleA(): """测试ModuleA(使用真实的A1和A2)""" module = ModuleA(ModuleA1(), ModuleA2()) result = module.process() assert result == "expected"
def test_main(): """测试Main(使用真实的所有模块)""" main = Main(ModuleA(), ModuleB()) result = main.run() assert result == "expected"
|
3. 三明治增量测试(Sandwich)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
|
def test_top_and_bottom(): """同时测试顶层和底层""" test_main_with_stubs() test_moduleA1() test_moduleA2()
def test_middle_layer(): """测试中间层""" test_moduleA() test_moduleB()
def test_integration(): """集成测试""" test_main_with_all_modules()
|
📋 增量测试流程
自顶向下流程
1 2 3 4 5 6 7 8 9 10 11
| 1. 测试主模块(使用桩) ↓ 2. 添加第一个子模块 ↓ 3. 测试主模块 + 第一个子模块 ↓ 4. 添加第二个子模块 ↓ 5. 测试主模块 + 两个子模块 ↓ 6. 重复直到所有模块添加完成
|
自底向上流程
1 2 3 4 5 6 7 8 9 10 11
| 1. 测试最底层模块 ↓ 2. 测试所有底层模块 ↓ 3. 使用驱动模块测试中间层 ↓ 4. 测试所有中间层模块 ↓ 5. 测试顶层模块 ↓ 6. 集成测试
|
🛠️ 桩模块和驱动模块
桩模块(Stub)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| class DatabaseStub: """数据库桩模块""" def query(self, sql): return [ {"id": 1, "name": "Alice"}, {"id": 2, "name": "Bob"} ]
def test_user_service_with_stub(): """使用桩模块测试UserService""" db = DatabaseStub() service = UserService(db) users = service.get_all_users() assert len(users) == 2
|
驱动模块(Driver)
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| class UserServiceDriver: """UserService驱动模块""" def test_get_user(self): user = get_user(user_id=1) assert user.id == 1 assert user.name == "Alice"
driver = UserServiceDriver() driver.test_get_user()
|
📊 最佳实践
1. 选择合适的增量策略
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| 自顶向下: ✅ 适合:控制流清晰的系统 ✅ 优势:早期发现设计问题 ❌ 劣势:需要大量桩模块
自底向上: ✅ 适合:数据流清晰的系统 ✅ 优势:不需要桩模块 ❌ 劣势:晚期发现设计问题
三明治: ✅ 适合:大型复杂系统 ✅ 优势:结合两者优势 ❌ 劣势:复杂度高
|
2. 使用Mock框架
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| from unittest.mock import Mock
def test_with_mock(): """使用Mock框架""" mock_db = Mock() mock_db.query.return_value = [ {"id": 1, "name": "Alice"} ] service = UserService(mock_db) users = service.get_all_users() assert len(users) == 1 mock_db.query.assert_called_once()
|
3. 持续集成
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| name: Incremental Tests
on: [push]
jobs: test-bottom-layer: runs-on: ubuntu-latest steps: - run: pytest tests/bottom_layer test-middle-layer: needs: test-bottom-layer runs-on: ubuntu-latest steps: - run: pytest tests/middle_layer test-top-layer: needs: test-middle-layer runs-on: ubuntu-latest steps: - run: pytest tests/top_layer
|
🔗 相关主题
- [[集成测试]] - 增量测试是集成测试的一种
- [[单元测试]] - 增量测试的基础
- [[系统测试]] - 增量测试的最终目标
💡 快速参考
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34
| 增量测试速查表 ================
定义:逐步添加模块并测试
增量测试类型: ⬇️ 自顶向下(Top-Down) ⬆️ 自底向上(Bottom-Up) 🥪 三明治(Sandwich)
核心概念: - 桩模块(Stub):模拟下层模块 - 驱动模块(Driver):模拟上层模块
增量 vs Big Bang: - 增量:逐步添加、容易定位 - Big Bang:一次性、难定位
最佳实践: 1. 选择合适的增量策略 2. 使用Mock框架 3. 持续集成 4. 自动化测试
优势: ✅ 问题容易定位 ✅ 风险低 ✅ 早期发现问题 ✅ 并行开发
适用场景: ✅ 大型系统 ✅ 复杂系统 ✅ 多人协作
|