一、单元测试基础概念

1. 定义与核心目标
- 定义:对软件中的最小可测试单元(如函数、类方法)进行正确性验证的测试活动。
- 核心目标:确保单元功能符合设计要求,发现代码逻辑错误、边界条件缺陷等。
2. 单元划分原则(作业手册单元4简答题)
- 划分依据:
- 程序模块的独立性(如单个函数、类的方法)。
- 详细设计说明书中的模块划分。
- 示例:
- 函数
int add(int a, int b)
可作为一个单元。
- 类
Calculator
中的sqrt(double x)
方法可独立测试。
3. 单元测试与其他测试阶段的区别
测试阶段 |
测试对象 |
测试方法 |
实施者 |
|
单元测试 |
单个模块 |
白盒测试为主 |
开发人员 |
|
集成测试 |
模块间接口 |
灰盒测试 |
测试工程师 |
|
系统测试 |
完整系统 |
黑盒测试 |
测试团队 |
|
二、单元测试实施基础
1. 测试依据与准备
- 依据文档:
- 详细设计说明书(模块功能规格说明)。
- 源代码清单(模块逻辑结构)。
- 测试环境:
- 单元测试框架(如JUnit)、测试驱动程序(模拟调用单元的代码)。
2. 单元测试主要任务(作业手册单元4简答题)
- 模块接口测试:验证输入/输出参数的正确性(如参数类型、数量、顺序)。
- 局部数据结构测试:检查变量初始化、赋值、作用域是否正确。
- 边界条件测试:测试模块在边界值(如数组越界、空值)下的处理。
- 独立路径测试:覆盖模块内的所有逻辑路径(结合白盒覆盖法)。
- 错误处理测试:验证异常情况(如输入非法数据)的处理逻辑。
3. 单元测试目标(作业手册单元4简答题)
- 确保模块功能正确实现,符合设计规格。
- 发现模块内的编码错误、逻辑缺陷和边界问题。
- 为后续集成测试提供可靠的单元模块。
三、JUnit框架核心技术(重点实践)
模块1:JUnit基础组件
1. 核心注解与类
- @Test:标注测试方法,表明该方法为一个测试用例。
- Assert类:包含断言方法(如
assertEquals
、assertThat
),用于验证实际结果与预期结果。
- TestCase类:测试类的基类,提供测试环境初始化(
setUp
)和清理(tearDown
)方法。
2. 测试流程方法
- setUp():在每个测试方法执行前初始化资源(如创建被测对象)。
- tearDown():在每个测试方法执行后释放资源(如关闭连接)。
- 示例:
public class CalculatorTest {
private Calculator calculator;
@Before
public void setUp() {
calculator = new Calculator();
}
@Test
public void testAdd() {
assertEquals(5, calculator.add(2, 3));
}
@After
public void tearDown() {
calculator = null;
}
}
模块2:断言与测试用例设计
1. 常用断言方法
2. 基于逻辑覆盖的测试用例设计
- 判定覆盖:覆盖模块内所有判定的真假分支(如
if
、while
的真假情况)。
- 示例(考试.docx第三单元代码):
public String tst(int x, int y) {
if(x>60 && y<35) {
} else if(x==25 && y>50) {
} else {
}
}
@Test public void testJ1Path() { tst(61, 34); }
@Test public void testJ3Path() { tst(25, 60); }
@Test public void testJ2Path() { tst(60, 35); }
四、单元测试综合实践(必考题型)
1. 单元测试步骤(作业手册单元4简答题)
- 分析模块规格:明确模块功能、输入输出、边界条件。
- 设计测试用例:基于白盒覆盖法(如判定覆盖、路径覆盖)设计用例。
- 编写测试代码:使用JUnit框架编写测试类,调用被测模块。
- 执行测试:运行测试用例,记录结果。
- 分析结果:对比预期与实际结果,追踪缺陷。
2. 参数化测试(@Parameters)
应用场景
- 同一测试逻辑需要多组数据输入时(如不同边界值测试)。
示例(考试.docx题目4):
@RunWith(Parameterized.class)
public class StringProcessorTest {
private StringProcessor processor = new StringProcessor();
private String input;
private String expected;
@Parameters
public static Collection<Object[]> testData() {
return Arrays.asList(new Object[][] {
{"abfdf", "替换前缀后的字符串为:effdf"},
{"cdsddscd", "替换cd后的字符串为:ghsddsgh"},
{"dfdsdf", "大写字母的字符串为:DFDSDF"}
});
}
public StringProcessorTest(String input, String expected) {
this.input = input;
this.expected = expected;
}
@Test
public void testProcess() {
assertEquals(expected, processor.process(input));
}
}
3. 单元测试与白盒覆盖结合
例题:三角形判断模块(考试.docx题目2)
public String test(int a, int b, int c) {
if (a<=0 || b<=0 || c<=0 || a>10 || b>10 || c>10) {
return "输入边值不在范围内";
}
if (a+b<=c || b+c<=a || a+c<=b) {
return "输入边值不能组成三角形";
}
if (a==b && b==c) {
return "能组成等边三角形";
} else if (a==b || b==c || a==c) {
return "能组成等腰三角形";
} else {
return "能组成普通三角形";
}
}
测试用例设计(判定覆盖):
- 输入边值不在范围内:a=0, b=1, c=1 → 预期结果“输入边值不在范围内”。
- 不能组成三角形:a=1, b=5, c=1 → 预期结果“输入边值不能组成三角形”。
- 等边三角形:a=3, b=3, c=3 → 预期结果“能组成等边三角形”。
- 等腰三角形:a=3, b=3, c=5 → 预期结果“能组成等腰三角形”。
- 普通三角形:a=4, b=2, c=5 → 预期结果“能组成普通三角形”。