软件测试

软件测试

2025年06月22日
1266 字 · 8 分钟

📅 时间: 06:37
🌤️ 天气: 银川 19~30℃ 多云

妇姑相唤浴蚕去,闲看中庭栀子花。

— 王建 · 《雨过山村》

正文

JAVA
// 1. 导入必要的 JUnit 5 包
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.Arguments;
import org.junit.jupiter.params.provider.MethodSource;
import java.util.stream.Stream;
import static org.junit.jupiter.api.Assertions.assertEquals;

/**
 * StringProblem 类的参数化测试类
 */
public class StringProblemTest {

    // 2. 编写一个静态方法作为测试数据源
    private static Stream<Arguments> provideTestData() {
        return Stream.of(
            // --- 场景一:测试前缀为 "ab" 的情况 ---
            // 覆盖 "if (str.matches(reg1))" 分支
            Arguments.of("abcdef", "替换前缀后的字符串为:efcdef"),
            // 边界情况:同时满足前缀 "ab" 和后缀 "cd",应优先执行第一个 if 条件
            Arguments.of("abcd", "替换前缀后的字符串为:efcd"),

            // --- 场景二:测试后缀为 "cd" 且前缀不为 "ab" 的情况 ---
            // 覆盖 "else if (str.matches(reg2))" 分支
            Arguments.of("xyzcd", "替换cd后的字符串为:xyzgh"),
            // 包含多个 "cd",验证 replaceAll 的效果
            Arguments.of("cdtestcd", "替换cd后的字符串为:ghtestgh"),

            // --- 场景三:测试其他所有情况 (转大写) ---
            // 覆盖 "else" 分支
            Arguments.of("hello", "大写字母的字符串为:HELLO"),
            // "ab" 不在开头
            Arguments.of("testab", "大写字母的字符串为:TESTAB"),
            // "cd" 不在结尾
            Arguments.of("cdtest", "大写字母的字符串为:CDTEST"),
            // 空字符串
            Arguments.of("", "大写字母的字符串为:")
        );
    }

    // 3. 编写参数化测试方法
    @ParameterizedTest
    @MethodSource("provideTestData")
    public void testChangeStr(String input, String expectedOutput) {
        // 调用被测试的方法,获取实际输出
        String actualOutput = StringProblem.changeStr(input);

        // 使用断言,验证实际输出与预期输出是否一致
        assertEquals(expectedOutput, actualOutput);
    }
}
JAVA
// 1. 导入必要的 JUnit 5 包
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.Arguments;
import org.junit.jupiter.params.provider.MethodSource;
import java.util.stream.Stream;
import static org.junit.jupiter.api.Assertions.assertEquals;

/**
 * CommissionProblem 类的参数化测试类
 */
public class CommissionProblemTest {

    // 2. 编写一个静态方法作为测试数据源
    private static Stream<Arguments> provideCommissionTestData() {
        return Stream.of(
            // --- 场景一:输入数据无效 ---
            // 枪机数量超过上限
            Arguments.of(new Integer[]{71, 50, 50}, "输入数据不合理!"),
            // 枪托数量低于下限
            Arguments.of(new Integer[]{30, 0, 30}, "输入数据不合理!"),
            // 枪管数量超过上限
            Arguments.of(new Integer[]{20, 20, 91}, "输入数据不合理!"),

            // --- 场景二:测试佣金第一档 (销售额 <= 1000) ---
            // 销售额: 10*45 + 10*30 + 10*25 = 450+300+250 = 1000. 佣金: 1000*0.1=100
            Arguments.of(new Integer[]{10, 10, 10}, "佣金为:100.0美元"),
            // 销售额: 1*45 + 1*30 + 1*25 = 100. 佣金: 100*0.1=10
            Arguments.of(new Integer[]{1, 1, 1}, "佣金为:10.0美元"),

            // --- 场景三:测试佣金第二档 (1000 < 销售额 <= 1800) ---
            // 销售额: 20*45+20*30+10*25 = 900+600+250 = 1750
            // 佣金: 1000*0.1 + (1750-1000)*0.15 = 100 + 750*0.15 = 100 + 112.5 = 212.5
            Arguments.of(new Integer[]{20, 20, 10}, "佣金为:212.5美元"),
            // 边界值测试:销售额正好为 1800 美元
            // 销售额: 20*45+20*30+12*25 = 900+600+300 = 1800
            // 佣金: 1000*0.1 + (1800-1000)*0.15 = 100 + 800*0.15 = 100 + 120 = 220
            Arguments.of(new Integer[]{20, 20, 12}, "佣金为:220.0美元"),

            // --- 场景四:测试佣金第三档 (销售额 > 1800) ---
            // 销售额: 30*45+30*30+30*25 = 1350+900+750 = 3000
            // 佣金: 1000*0.1 + 800*0.15 + (3000-1800)*0.2 = 100 + 120 + 1200*0.2 = 220 + 240 = 460
            Arguments.of(new Integer[]{30, 30, 30}, "佣金为:460.0美元"),
            // 最大销售量测试
            // 销售额: 70*45+80*30+90*25 = 3150+2400+2250 = 7800
            // 佣金: 1000*0.1 + 800*0.15 + (7800-1800)*0.2 = 100 + 120 + 6000*0.2 = 220 + 1200 = 1420
            Arguments.of(new Integer[]{70, 80, 90}, "佣金为:1420.0美元")
        );
    }

    // 3. 编写参数化测试方法
    @ParameterizedTest
    @MethodSource("provideCommissionTestData")
    public void testSumCommission(Integer[] inputSales, String expectedResult) {
        // 创建 CommissionProblem 实例
        CommissionProblem commissionProblem = new CommissionProblem();
        
        // 调用被测试的方法,获取实际输出
        String actualResult = commissionProblem.sumCommission(inputSales);

        // 使用断言,验证实际输出与预期输出是否一致
        assertEquals(expectedResult, actualResult);
    }
}

**代码关键点解析

  1. 测试用例设计是核心:

    • 无效数据: 必须测试所有导致 checkDate 返回 false 的情况(上、下限)。

    • 有效数据: 要覆盖所有佣金计算档位 (if, else if, else)。

    • 边界值测试: 这是测试的精髓。要测试每个档位的临界点,例如销售额正好是 1000 美元、1800 美元的情况,以及刚好超过 1800 美元的情况。这能最有效地发现逻辑错误。

    • 典型值/极值测试: 测试一个普通的中间值(如销售额1750),以及最大销售量的情况,确保计算在各种范围内都正确。

  2. provideCommissionTestData() 数据源方法:

    • 注意输入参数的类型是 new Integer[]{…},因为方法需要一个数组对象。

    • 每个 Arguments.of(…) 都精确对应一个测试场景,注释清晰地说明了该场景的计算过程和预期结果,这在考试中是展示你思维过程的好方法。

  3. testSumCommission(…) 测试方法:

    • 与上一题不同,sumCommission 不是静态方法,所以在测试方法内部需要先 new CommissionProblem() 创建一个实例,然后才能调用它的方法。

    • assertEquals(expectedResult, actualResult) 的作用依然是比较预期与实际,确保代码按预期工作。


Thanks for reading!

软件测试

2025年06月22日
1266 字 · 8 分钟