增量测试(Incremental Testing)

增量测试(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
# 系统结构:
# Main
# ├── ModuleA
# │ ├── ModuleA1
# │ └── ModuleA2
# └── ModuleB
# ├── ModuleB1
# └── ModuleB2

# 测试顺序:
# 1. 测试Main(使用桩模块)
def test_main_with_stubs():
"""测试Main,使用桩模块"""
# 创建桩模块
class StubModuleA:
def process(self):
return "stub_result"

class StubModuleB:
def process(self):
return "stub_result"

# 测试Main
main = Main(StubModuleA(), StubModuleB())
result = main.run()
assert result is not None

# 2. 添加ModuleA,测试Main + ModuleA
def test_main_with_moduleA():
"""测试Main + ModuleA"""
main = Main(ModuleA(), StubModuleB())
result = main.run()
assert result is not None

# 3. 添加ModuleB,测试Main + ModuleA + ModuleB
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
# 测试顺序:
# 1. 测试最底层模块
def test_moduleA1():
"""测试ModuleA1"""
module = ModuleA1()
result = module.process()
assert result == "expected"

def test_moduleA2():
"""测试ModuleA2"""
module = ModuleA2()
result = module.process()
assert result == "expected"

# 2. 测试中间层模块
def test_moduleA():
"""测试ModuleA(使用真实的A1和A2)"""
module = ModuleA(ModuleA1(), ModuleA2())
result = module.process()
assert result == "expected"

# 3. 测试顶层模块
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
# 结合自顶向下和自底向上
# 1. 同时测试顶层和底层
def test_top_and_bottom():
"""同时测试顶层和底层"""
# 测试顶层
test_main_with_stubs()

# 测试底层
test_moduleA1()
test_moduleA2()

# 2. 测试中间层
def test_middle_layer():
"""测试中间层"""
test_moduleA()
test_moduleB()

# 3. 集成测试
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对象
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
# .github/workflows/incremental-test.yml
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. 自动化测试

优势:
✅ 问题容易定位
✅ 风险低
✅ 早期发现问题
✅ 并行开发

适用场景:
✅ 大型系统
✅ 复杂系统
✅ 多人协作