📅 时间: 06:37
🌤️ 天气: 银川 19~30℃ 多云
妇姑相唤浴蚕去,闲看中庭栀子花。
— 王建 · 《雨过山村》
正文
// 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);
}
}// 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);
}
}**代码关键点解析
测试用例设计是核心:
无效数据: 必须测试所有导致 checkDate 返回 false 的情况(上、下限)。
有效数据: 要覆盖所有佣金计算档位 (if, else if, else)。
边界值测试: 这是测试的精髓。要测试每个档位的临界点,例如销售额正好是 1000 美元、1800 美元的情况,以及刚好超过 1800 美元的情况。这能最有效地发现逻辑错误。
典型值/极值测试: 测试一个普通的中间值(如销售额1750),以及最大销售量的情况,确保计算在各种范围内都正确。
provideCommissionTestData() 数据源方法:
注意输入参数的类型是 new Integer[]{…},因为方法需要一个数组对象。
每个 Arguments.of(…) 都精确对应一个测试场景,注释清晰地说明了该场景的计算过程和预期结果,这在考试中是展示你思维过程的好方法。
testSumCommission(…) 测试方法:
与上一题不同,sumCommission 不是静态方法,所以在测试方法内部需要先 new CommissionProblem() 创建一个实例,然后才能调用它的方法。
assertEquals(expectedResult, actualResult) 的作用依然是比较预期与实际,确保代码按预期工作。
Thanks for reading!
