课堂作业:黑盒测试
实验一 黑盒测试
一、实验目的
1、掌握黑盒测试的基础知识;
2、掌握黑盒测试的检查内容及测试目的;
3、掌握黑盒测试的几种基本测试方法:等价类划分方法、边界值分析方法、因果图法、决策表法和场景法;
二、实验要求
1、复习有关内容,理解黑盒测试;
2、掌握等价类划分、边界值分析方法、因果图法和决策表法,并能设计出测试用例;
3、对具体软件,能分别使用相应的黑盒测试方法设计测试用例,并实施测试、分析测试结果。
三、实验内容
1、设计函数实现输入日期显示星期几,并用等价类及边界值法测试
实验步骤:
①设计程序
const readline = require('readline');
function getWeekday(dateStr) {
// 输入验证
if (!dateStr || typeof dateStr !== 'string') {
return '请输入有效的日期字符串';
}
// 处理不规范的日期格式,自动补全月份和日期的前导零
const parts = dateStr.split('-');
if (parts.length === 3) {
const year = parts[0];
const month = parts[1].padStart(2, '0');
const day = parts[2].padStart(2, '0');
dateStr = `${year}-${month}-${day}`;
}
// 创建日期对象(使用UTC时间避免时区影响)
const date = new Date(dateStr + 'T00:00:00Z');
// 检查日期是否有效
if (isNaN(date.getTime())) {
return '请输入有效的日期格式,如:YYYY-MM-DD';
}
// 定义星期几数组
const weekdays = ['星期日', '星期一', '星期二', '星期三', '星期四', '星期五', '星期六'];
// 返回对应的星期几
return weekdays[date.getUTCDay()];
}
// 创建readline接口
const rl = readline.createInterface({
input: process.stdin,
output: process.stdout
});
// 提示用户输入日期
rl.question('请输入日期(格式:YYYY-MM-DD):', (dateStr) => {
// 调用函数并显示结果
const result = getWeekday(dateStr);
console.log('该日期是:', result);
// 关闭接口
rl.close();
});
②划分等价类,得到等价类表。等价类表格式如下:
| 输入条件 | 有效等价类 | 唯一标识 | 无效等价类 | 唯一标识 |
|---|---|---|---|---|
| 输入类型 | 字符串类型 | V1 | 非字符串类型 | I1 |
| 日期格式 | 符合YYYY-MM-DD格式 | V2 | 格式错误 | I2 |
| 年份 | 4位数字年份 | V3 | 非 4 位数字年份(如 3 位或 5 位) | I3 |
| 月份 | 1-12 的有效月份(含前导零和无前导零) | V4 | 月份 < 1 或 > 12 | I4 |
| 日期 | 对应月份的有效日期 | V5 | 日期 < 1 或超过对应月份的最大天数 | I5 |
| 闰年判断 | 闰年的 2 月 29 日 | V6 | 非闰年的 2 月 29 日 | I6 |
| 输入长度 | 非空字符串 | V7 | 空字符串 | I7 |
③运用等价类划分法设计测试用例,得到测试用例表。测试用例表格式如下:
| 序号 | 输入数据 | 覆盖等价类 | 输出 |
|---|---|---|---|
| 1 | "2026-04-08" | V1, V2, V3, V4, V5, V7 | 星期三 |
| 2 | "2026-4-8" | V1, V2, V3, V4, V5, V7 | 星期三 |
| 3 | "2024-02-29" | V1, V2, V3, V4, V5, V6, V7 | 星期四 |
| 4 | "2026-01-01" | V1, V2, V3, V4, V5, V7 | 星期四 |
| 5 | "2026-12-31" | V1, V2, V3, V4, V5, V7 | 星期四 |
| 6 | "2026-04-30" | V1, V2, V3, V4, V5, V7 | 星期四 |
| 7 | "2025-02-28" | V1, V2, V3, V4, V5, V7 | 星期五 |
| 8 | 123 | I1 | 请输入有效的日期字符串 |
| 9 | "2026/04/08" | I2 | 请输入有效的日期格式,如:YYYY-MM-DD |
| 10 | "2026-04" | I2 | 请输入有效的日期格式,如:YYYY-MM-DD |
| 11 | "26-04-08" | I3 | 请输入有效的日期格式,如:YYYY-MM-DD |
| 12 | "2026-13-01" | I4 | 请输入有效的日期格式,如:YYYY-MM-DD |
| 13 | "2026-00-01" | I4 | 请输入有效的日期格式,如:YYYY-MM-DD |
| 14 | "2026-01-32" | I5 | 请输入有效的日期格式,如:YYYY-MM-DD |
| 15 | "2026-04-31" | I5 | 请输入有效的日期格式,如:YYYY-MM-DD |
| 16 | "2025-02-29" | I6 | 请输入有效的日期格式,如:YYYY-MM-DD |
| 17 | "" | I7 | 请输入有效的日期字符串 |
④ 运用边界值法设计测试用例。
| 序号 | 输入数据 | 测试边界 | 预期输出 |
|---|---|---|---|
| 1 | "2026-01-01" | 月份下界(1月) | 星期四 |
| 2 | "2026-12-31" | 月份上界(12月) | 星期四 |
| 3 | "2026-04-01" | 日期下界(1日) | 星期三 |
| 4 | "2026-01-31" | 31天月份的日期上界 | 星期六 |
| 5 | "2026-04-30" | 30天月份的日期上界 | 星期四 |
| 6 | "2025-02-28" | 非闰年2月的日期上界 | 星期五 |
| 7 | "2024-02-29" | 闰年2月的日期上界 | 星期四 |
| 8 | "2026-00-01" | 月份下界-1(无效) | 请输入有效的日期格式,如:YYYY-MM-DD |
| 9 | "2026-13-01" | 月份上界+1(无效) | 请输入有效的日期格式,如:YYYY-MM-DD |
| 10 | "2026-01-00" | 日期下界-1(无效) | 请输入有效的日期格式,如:YYYY-MM-DD |
| 11 | "2026-01-32" | 31天月份的日期上界+1(无效) | 请输入有效的日期格式,如:YYYY-MM-DD |
| 12 | "2026-04-31" | 30天月份的日期上界+1(无效) | 请输入有效的日期格式,如:YYYY-MM-DD |
| 13 | "2025-02-29" | 非闰年2月的日期上界+1(无效) | 请输入有效的日期格式,如:YYYY-MM-DD |
| 14 | "2026-4-8" | 月份和日期无前导零(边界格式) | 星期三 |
| 15 | "2026-04-8" | 日期无前导零(边界格式) | 星期三 |
| 16 | "2026-4-08" | 月份无前导零(边界格式) | 星期三 |
2、找零钱最佳组合
假设商店货品价格(R) 都不大于100元(且为整数),若顾客付款(P)在100元内,现有一个程序能在每位顾客付款后给出找零钱的最佳组合(找给顾客货币张数最少)。 假定此商店的货币面值只包括:50元(N50)、10元(N10)、 5元(N5)、1元(N1) 四种。
请结合等价类划分法和边界值分析法为上述程序设计 出相应的测试用例。
实验步骤:
①设计程序
const readline = require('readline');
function calculateChange(price, payment) {
// 输入验证
if (typeof price !== 'number' || typeof payment !== 'number') {
return '请输入有效的数字';
}
if (!Number.isInteger(price) || !Number.isInteger(payment)) {
return '价格和付款金额必须是整数';
}
if (price < 0 || price > 100) {
return '货品价格必须在0-100元之间';
}
if (payment < 0 || payment > 100) {
return '付款金额必须在0-100元之间';
}
if (payment < price) {
return '付款金额不足';
}
// 计算找零金额
const change = payment - price;
if (change === 0) {
return '无需找零';
}
// 货币面值(从大到小排列)
const denominations = [50, 10, 5, 1];
const changeDetails = {
N50: 0,
N10: 0,
N5: 0,
N1: 0
};
let remainingChange = change;
// 贪心算法计算最佳找零组合
for (let i = 0; i < denominations.length; i++) {
const denomination = denominations[i];
const count = Math.floor(remainingChange / denomination);
if (count > 0) {
switch (denomination) {
case 50:
changeDetails.N50 = count;
break;
case 10:
changeDetails.N10 = count;
break;
case 5:
changeDetails.N5 = count;
break;
case 1:
changeDetails.N1 = count;
break;
}
remainingChange -= count * denomination;
}
}
// 计算总张数
const totalNotes = changeDetails.N50 + changeDetails.N10 + changeDetails.N5 + changeDetails.N1;
return {
change: change,
totalNotes: totalNotes,
details: changeDetails
};
}
// 创建readline接口
const rl = readline.createInterface({
input: process.stdin,
output: process.stdout
});
// 提示用户输入价格和付款金额
rl.question('请输入货品价格(0-100元之间的整数):', (priceStr) => {
const price = parseInt(priceStr);
rl.question('请输入付款金额(0-100元之间的整数):', (paymentStr) => {
const payment = parseInt(paymentStr);
// 调用函数并显示结果
const result = calculateChange(price, payment);
if (typeof result === 'string') {
console.log('结果:', result);
} else {
console.log('找零金额:', result.change, '元');
console.log('最少货币张数:', result.totalNotes, '张');
console.log('找零组合:');
if (result.details.N50 > 0) {
console.log('50元:', result.details.N50, '张');
}
if (result.details.N10 > 0) {
console.log('10元:', result.details.N10, '张');
}
if (result.details.N5 > 0) {
console.log('5元:', result.details.N5, '张');
}
if (result.details.N1 > 0) {
console.log('1元:', result.details.N1, '张');
}
}
// 关闭接口
rl.close();
});
});
②划分等价类,得到等价类表。等价类表格式如下:
| 输入条件 | 有效等价类 | 唯一标识 | 无效等价类 | 唯一标识 |
|---|---|---|---|---|
| 输入类型 | 字符串类型 | V1 | 非字符串类型 | I1 |
| 日期格式 | 符合YYYY-MM-DD格式 | V2 | 格式错误 | I2 |
| 年份 | 4位数字年份 | V3 | 非 4 位数字年份(如 3 位或 5 位) | I3 |
| 月份 | 1-12 的有效月份(含前导零和无前导零) | V4 | 月份 < 1 或 > 12 | I4 |
| 日期 | 对应月份的有效日期 | V5 | 日期 < 1 或超过对应月份的最大天数 | I5 |
| 闰年判断 | 闰年的 2 月 29 日 | V6 | 非闰年的 2 月 29 日 | I6 |
| 输入长度 | 非空字符串 | V7 | 空字符串 | I7 |
④运用等价类划分法设计测试用例,得到测试用例表。测试用例表格式如下:
| 序号 | 输入数据 | 覆盖等价类 | 输出 |
|---|---|---|---|
| 1 | 价格 = 50, 付款 = 50 | V1, V2, V3, V4, V5, V6, V7, V8 | 无需找零 |
| 2 | 价格 = 23, 付款 = 50 | V1, V2, V3, V4, V5, V6, V7, V9 | 找零金额:27 元最少货币张数:5 张找零组合:10 元:2 张,5 元:1 张,1 元:2 张 |
| 3 | 价格 = 0, 付款 = 100 | V1, V2, V3, V4, V5, V6, V7, V9 | 找零金额:100 元最少货币张数:2 张找零组合:50 元:2 张 |
| 4 | 价格 = 100, 付款 = 100 | V1, V2, V3, V4, V5, V6, V7, V8 | 无需找零 |
| 5 | 价格 = 45, 付款 = 100 | V1, V2, V3, V4, V5, V6, V7, V9 | 找零金额:55 元最少货币张数:2 张找零组合:50 元:1 张,5 元:1 张 |
| 6 | 价格 ="23", 付款 = 50 | I1 | 请输入有效的数字 |
| 7 | 价格 = 23.5, 付款 = 50 | I2 | 价格和付款金额必须是整数 |
| 8 | 价格 =-10, 付款 = 50 | I3 | 货品价格必须在 0-100 元之间 |
| 9 | 价格 = 150, 付款 = 200 | I4 | 货品价格必须在 0-100 元之间 |
| 10 | 价格 = 23, 付款 ="50" | I5 | 请输入有效的数字 |
| 11 | 价格 = 23, 付款 = 50.5 | I6 | 价格和付款金额必须是整数 |
| 12 | 价格 = 23, 付款 =-10 | I7 | 付款金额必须在 0-100 元之间 |
| 13 | 价格 = 23, 付款 = 150 | I8 | 付款金额必须在 0-100 元之间 |
| 14 | 价格 = 50, 付款 = 23 | I9 | 付款金额不足 |
⑤运用边界值法设计测试用例。
| 序号 | 输入数据 | 覆盖等价类 | 输出 |
|---|---|---|---|
| 1 | 价格 = 0, 付款 = 0 | 价格下界,付款下界 | 无需找零 |
| 2 | 价格 = 0, 付款 = 1 | 价格下界,付款最小正整数 | 找零金额:1 元最少货币张数:1 张找零组合:1 元:1 张 |
| 3 | 价格 = 0, 付款 = 100 | 价格下界,付款上界 | 找零金额:100 元最少货币张数:2 张找零组合:50 元:2 张 |
| 4 | 价格 = 1, 付款 = 1 | 价格最小正整数,付款等于价格 | 无需找零 |
| 5 | 价格 = 1, 付款 = 2 | 价格最小正整数,付款比价格大 1 | 找零金额:1 元最少货币张数:1 张找零组合:1 元:1 张 |
| 6 | 价格 = 99, 付款 = 99 | 价格最大正整数,付款等于价格 | 无需找零 |
| 7 | 价格 = 99, 付款 = 100 | 价格最大正整数,付款上界 | 找零金额:1 元最少货币张数:1 张找零组合:1 元:1 张 |
| 8 | 价格 = 100, 付款 = 100 | 价格上界,付款上界 | 无需找零 |
| 9 | 价格 = 100, 付款 = 101 | 价格上界,付款超过上界 | 付款金额必须在 0-100 元之间 |
| 10 | 价格 =-1, 付款 = 50 | 价格低于下界 | 货品价格必须在 0-100 元之间 |
| 11 | 价格 = 101, 付款 = 150 | 价格超过上界 | 货品价格必须在 0-100 元之间 |
| 12 | 价格 = 50, 付款 =-1 | 付款低于下界 | 付款金额必须在 0-100 元之间 |
| 13 | 价格 = 50, 付款 = 101 | 付款超过上界 | 付款金额必须在 0-100 元之间 |
| 14 | 价格 = 50, 付款 = 49 | 付款比价格小 1 | 付款金额不足 |
| 15 | 价格 = 45, 付款 = 50 | 找零金额 = 5(5 元面值边界) | 找零金额:5 元最少货币张数:1 张找零组合:5 元:1 张 |
| 16 | 价格 = 40, 付款 = 50 | 找零金额 = 10(10 元面值边界) | 找零金额:10 元最少货币张数:1 张找零组合:10 元:1 张 |
| 17 | 价格 = 0, 付款 = 50 | 找零金额 = 50(50 元面值边界) | 找零金额:50 元最少货币张数:1 张找零组合:50 元:1 张 |
3、有一个饮料自动售货机(处理单价为5角钱)的控制处理软件,它的软件规格说明如下:
若投入5角钱的硬币,按下“橙汁”或“啤酒”的按钮,则相应的饮料就送出来。若投入1元钱的硬币,同样也是按“橙汁”或“啤酒”的按钮,则自动售货机在送出相应饮料的同时退回5角钱的硬币。
模拟程序如下:
用因果图法测试该程序,并撰写实验报告。
实验步骤:
①编写程序
const readline = require('readline');
function vendingMachine(coin, drink) {
// 输入验证
if (!coin || !drink) {
return '请输入硬币金额和饮料类型';
}
// 验证硬币金额
if (coin !== 0.5 && coin !== 1) {
return '只接受5角和1元的硬币';
}
// 验证饮料类型
if (drink !== '橙汁' && drink !== '啤酒') {
return '只提供橙汁和啤酒';
}
// 处理购买逻辑
if (coin === 0.5) {
return `已送出${drink}`;
} else if (coin === 1) {
return `已送出${drink},并退回5角硬币`;
}
}
// 创建readline接口
const rl = readline.createInterface({
input: process.stdin,
output: process.stdout
});
// 提示用户输入硬币金额和饮料类型
rl.question('请投入硬币金额(0.5或1):', (coinStr) => {
const coin = parseFloat(coinStr);
rl.question('请选择饮料类型(橙汁或啤酒):', (drink) => {
// 调用函数并显示结果
const result = vendingMachine(coin, drink);
console.log('操作结果:', result);
// 关闭接口
rl.close();
});
});
②分析原因与结果,与同学交换程序测试。
编号 原因 说明
| 编号 | 原因 | 说明 |
|---|---|---|
| C1 | 硬币金额为0.5元 | 投入5角硬币 |
| C2 | 硬币金额为1元 | 投入1元硬币 |
| C3 | 选择橙汁 | 选择橙汁饮料 |
| C4 | 选择啤酒 | 选择啤酒饮料 |
| C5 | 硬币金额无效 | 投入非0.5元和1元的硬币 |
| C6 | 饮料类型无效 | 选择非橙汁和啤酒的饮料 |
| C7 | 输入不完整 | 未输入硬币金额或饮料类型 |
| 编号 | 结果 | 说明 |
|---|---|---|
| E1 | 送出橙汁 | 成功购买橙汁 |
| E2 | 送出啤酒 | 成功购买啤酒 |
| E3 | 退回5角硬币 | 投入1元硬币时的找零 |
| E4 | 提示"只接受5角和1元的硬币" | 硬币金额无效 |
| E5 | 提示"只提供橙汁和啤酒" | 饮料类型无效 |
| E6 | 提示"请输入硬币金额和饮料类型" | 输入不完整 |
③画出因果图

④转化为决策表
| 规则编号 | C1 (0.5元) | C2 (1元) | C3 (橙汁) | C4 (啤酒) | C5 (金额无效) | C6 (饮料无效) | C7 (输入不完整) | E1 (送出橙汁) | E2 (送出啤酒) | E3 (退5角) | E4 (金额错误) | E5 (饮料错误) | E6 (输入错误) |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 1 | Y | N | Y | N | N | N | N | Y | N | N | N | N | N |
| 2 | Y | N | N | Y | N | N | N | N | Y | N | N | N | N |
| 3 | N | Y | Y | N | N | N | N | Y | N | Y | N | N | N |
| 4 | N | Y | N | Y | N | N | N | N | Y | Y | N | N | N |
| 5 | N | N | Y | N | Y | N | N | N | N | N | Y | N | N |
| 6 | N | N | N | Y | Y | N | N | N | N | N | Y | N | N |
| 7 | Y | N | N | N | N | Y | N | N | N | N | N | Y | N |
| 8 | N | Y | N | N | N | Y | N | N | N | N | N | Y | N |
| 9 | N | N | Y | N | N | Y | N | N | N | N | N | Y | N |
| 10 | N | N | N | Y | N | Y | N | N | N | N | N | Y | N |
| 11 | Y | N | Y | N | N | N | Y | N | N | N | N | N | Y |
| 12 | Y | N | N | Y | N | N | Y | N | N | N | N | N | Y |
| 13 | N | Y | Y | N | N | N | Y | N | N | N | N | N | Y |
| 14 | N | Y | N | Y | N | N | Y | N | N | N | N | N | Y |
| 15 | N | N | Y | N | Y | N | Y | N | N | N | N | N | Y |
| 16 | N | N | N | Y | Y | N | Y | N | N | N | N | N | Y |
| 17 | Y | N | N | N | N | Y | Y | N | N | N | N | N | Y |
| 18 | N | Y | N | N | N | Y | Y | N | N | N | N | N | Y |
| 19 | N | N | N | N | N | N | Y | N | N | N | N | N | Y |
⑤根据决策表设计测试用例,得到测试用例表
| 测试用例编号 | 输入数据 | 覆盖规则 | 预期输出 |
|---|---|---|---|
| TC1 | 硬币=0.5元,饮料=橙汁 | 规则1 | 已送出橙汁 |
| TC2 | 硬币=0.5元,饮料=啤酒 | 规则2 | 已送出啤酒 |
| TC3 | 硬币=1元,饮料=橙汁 | 规则3 | 已送出橙汁,并退回5角硬币 |
| TC4 | 硬币=1元,饮料=啤酒 | 规则4 | 已送出啤酒,并退回5角硬币 |
| TC5 | 硬币=0.2元,饮料=橙汁 | 规则5 | 只接受5角和1元的硬币 |
| TC6 | 硬币=1.5元,饮料=啤酒 | 规则6 | 只接受5角和1元的硬币 |
| TC7 | 硬币=0.5元,饮料=可乐 | 规则7 | 只提供橙汁和啤酒 |
| TC8 | 硬币=1元,饮料=雪碧 | 规则8 | 只提供橙汁和啤酒 |
| TC9 | 硬币=空,饮料=橙汁 | 规则11 | 请输入硬币金额和饮料类型 |
| TC10 | 硬币=0.5元,饮料=空 | 规则12 | 请输入硬币金额和饮料类型 |
| TC11 | 硬币=空,饮料=空 | 规则19 | 请输入硬币金额和饮料类型 |
4、航空服务查询问题:根据航线,仓位,飞行时间查询航空服务。
假设一个中国的航空公司规定:
① 中国去欧美的航线所有座位都有食物供应,每个座位都可以播放电影。
② 中国去非欧美的国外航线都有食物供应,只有商务仓可以播放电影。
③ 中国国内的航班的商务仓有食物供应,但是不可以播放电影
④ 中国国内航班的经济仓只有当飞行时间大于2小时时才有食物供应,但是不可以播放电影。
请用程序实现上述功能,并用决策表法设计测试用例,再执行测试,撰写实验报告。
实验步骤:
①编写程序,与同学交换程序测试。
const readline = require('readline');
function queryAirlineService(route, seatClass, flightTime) {
// 输入验证
if (!route || !seatClass || flightTime === undefined) {
return '请输入完整的航线、仓位和飞行时间信息';
}
// 验证航线类型
const validRoutes = ['欧美', '非欧美', '国内'];
if (!validRoutes.includes(route)) {
return '航线类型必须是:欧美、非欧美或国内';
}
// 验证仓位类型
const validSeatClasses = ['商务仓', '经济仓', '商务舱', '经济舱'];
if (!validSeatClasses.includes(seatClass)) {
return '仓位类型必须是:商务仓(或商务舱)、经济仓(或经济舱)';
}
// 统一仓位类型格式
if (seatClass === '商务舱') seatClass = '商务仓';
if (seatClass === '经济舱') seatClass = '经济仓';
// 验证飞行时间
if (typeof flightTime !== 'number' || flightTime < 0) {
return '飞行时间必须是大于等于0的数字';
}
// 初始化服务信息
let hasFood = false;
let hasMovie = false;
// 根据规则判断服务
if (route === '欧美') {
// 中国去欧美的航线所有座位都有食物供应,每个座位都可以播放电影
hasFood = true;
hasMovie = true;
} else if (route === '非欧美') {
// 中国去非欧美的国外航线都有食物供应,只有商务仓可以播放电影
hasFood = true;
hasMovie = (seatClass === '商务仓');
} else if (route === '国内') {
if (seatClass === '商务仓') {
// 中国国内的航班的商务仓有食物供应,但是不可以播放电影
hasFood = true;
hasMovie = false;
} else if (seatClass === '经济仓') {
// 中国国内航班的经济仓只有当飞行时间大于2小时时才有食物供应,但是不可以播放电影
hasFood = (flightTime > 2);
hasMovie = false;
}
}
return {
route: route,
seatClass: seatClass,
flightTime: flightTime,
hasFood: hasFood,
hasMovie: hasMovie
};
}
// 创建readline接口
const rl = readline.createInterface({
input: process.stdin,
output: process.stdout
});
// 提示用户输入信息
rl.question('请输入航线类型(欧美、非欧美、国内):', (route) => {
rl.question('请输入仓位类型(商务仓、经济仓):', (seatClass) => {
rl.question('请输入飞行时间(小时):', (flightTimeStr) => {
const flightTime = parseFloat(flightTimeStr);
// 调用函数并显示结果
const result = queryAirlineService(route, seatClass, flightTime);
if (typeof result === 'string') {
console.log('结果:', result);
} else {
console.log('查询结果:');
console.log('航线类型:', result.route);
console.log('仓位类型:', result.seatClass);
console.log('飞行时间:', result.flightTime, '小时');
console.log('是否有食物供应:', result.hasFood ? '是' : '否');
console.log('是否可以播放电影:', result.hasMovie ? '是' : '否');
}
// 关闭接口
rl.close();
});
});
});
②构造决策表
| 规则编号 | 航线类型 | 仓位类型 | 飞行时间 | 食物供应 | 电影播放 |
|---|---|---|---|---|---|
| 1 | 欧美 | 商务仓 | >2小时 | 是 | 是 |
| 2 | 欧美 | 商务仓 | ≤2小时 | 是 | 是 |
| 3 | 欧美 | 经济仓 | >2小时 | 是 | 是 |
| 4 | 欧美 | 经济仓 | ≤2小时 | 是 | 是 |
| 5 | 非欧美 | 商务仓 | >2小时 | 是 | 是 |
| 6 | 非欧美 | 商务仓 | ≤2小时 | 是 | 是 |
| 7 | 非欧美 | 经济仓 | >2小时 | 是 | 否 |
| 8 | 非欧美 | 经济仓 | ≤2小时 | 是 | 否 |
| 9 | 国内 | 商务仓 | >2小时 | 是 | 否 |
| 10 | 国内 | 商务仓 | ≤2小时 | 是 | 否 |
| 11 | 国内 | 经济仓 | >2小时 | 是 | 否 |
| 12 | 国内 | 经济仓 | ≤2小时 | 否 | 否 |
③根据决策表设计测试用例,得到测试用例表
| 测试用例编号 | 输入数据 | 覆盖规则 | 预期输出 |
|---|---|---|---|
| TC1 | 航线=欧美,仓位=商务仓,飞行时间=3小时 | 规则1 | 食物供应=是,电影播放=是 |
| TC2 | 航线=欧美,仓位=经济仓,飞行时间=1小时 | 规则4 | 食物供应=是,电影播放=是 |
| TC3 | 航线=非欧美,仓位=商务仓,飞行时间=2小时 | 规则6 | 食物供应=是,电影播放=是 |
| TC4 | 航线=非欧美,仓位=经济仓,飞行时间=4小时 | 规则7 | 食物供应=是,电影播放=否 |
| TC5 | 航线=国内,仓位=商务仓,飞行时间=5小时 | 规则9 | 食物供应=是,电影播放=否 |
| TC6 | 航线=国内,仓位=经济仓,飞行时间=3小时 | 规则11 | 食物供应=是,电影播放=否 |
| TC7 | 航线=国内,仓位=经济仓,飞行时间=2小时 | 规则12 | 食物供应=否,电影播放=否 |
5、旅馆住宿系统中,旅馆业主可进行添加房间操作。
–旅馆业主登录旅馆住宿系统后,可以请求添加房间;
–待进入“房间管理”对话框,单击“添加”按钮可进行添加房间操作;
–添加房间时,可以设定房间的房间编号、房间类型、房间描述信息;
–添加房间信息不能缺失,若某一项未填写,要给出提示信息;
–房间编号长度不超过5个字符;
–房间描述长度不超过1000个字符;
–房间信息不能重复,成功填写后,可进行保存或取消操作,之后返回“房间管理”对话框,结束添加房间流程。
实验步骤:
利用黑盒测试策略编写添加房间功能的测试用例。
| 测试用例编号 | 测试场景 | 输入数据 | 预期结果 | 测试类型 |
|---|---|---|---|---|
| TC1 | 正常添加房间 | 房间编号:101房间类型:单人间房间描述:舒适单人间,带独立卫浴 | 添加成功,返回房间管理对话框 | 正常测试 |
| TC2 | 房间编号为空 | 房间编号:<空>房间类型:双人间房间描述:标准双人间 | 提示 "房间编号不能为空" | 异常测试 |
| TC3 | 房间类型为空 | 房间编号:201房间类型:<空>房间描述:豪华双人间 | 提示 "房间类型不能为空" | 异常测试 |
| TC4 | 房间描述为空 | 房间编号:301房间类型:套房房间描述:<空> | 提示 "房间描述不能为空" | 异常测试 |
| TC5 | 所有信息为空 | 房间编号:<空>房间类型:<空>房间描述:<空> | 提示 "所有信息不能为空" | 异常测试 |
| TC6 | 房间编号长度超过限制 | 房间编号:100012房间类型:单人间房间描述:标准单人间 | 提示 "房间编号长度不能超过 5 个字符" | 异常测试 |
| TC7 | 房间描述长度超过限制 | 房间编号:401房间类型:双人间房间描述:[1001 个字符的描述] | 提示 "房间描述长度不能超过 1000 个字符" | 异常测试 |
| TC8 | 房间信息重复 | 房间编号:101(已存在)房间类型:单人间房间描述:舒适单人间 | 提示 "房间信息已存在" | 异常测试 |
| TC9 | 保存操作 | 填写完整信息后点击 "保存" | 保存成功,返回房间管理对话框 | 功能测试 |
| TC10 | 取消操作 | 填写信息后点击 "取消" | 不保存信息,返回房间管理对话框 | 功能测试 |
| TC11 | 房间编号刚好 5 个字符 | 房间编号:ABCDE房间类型:单人间房间描述:标准单人间 | 添加成功,返回房间管理对话框 | 边界测试 |
| TC12 | 房间描述刚好 1000 个字符 | 房间编号:501房间类型:套房房间描述:[1000 个字符的描述] | 添加成功,返回房间管理对话框 | 边界测试 |
6、使用正交实验法中讲授的工具,对课件上的这部分任选1道例题,进行测试用例的设计。
| 测试用例编号 | 输入数据 (x,y) | 测试边界 | 说明 |
|---|---|---|---|
| TC1 | (1,15) | x的最小值 | 测试x取最小值时的函数行为 |
| TC2 | (2,15) | x的最小值+1 | 测试x接近最小值时的函数行为 |
| TC3 | (11,15) | x的最大值-1 | 测试x接近最大值时的函数行为 |
| TC4 | (12,15) | x的最大值 | 测试x取最大值时的函数行为 |
| TC5 | (6,15) | x和y的中间值 | 测试x和y都取中间值时的函数行为 |
| TC6 | (6,1) | y的最小值 | 测试y取最小值时的函数行为 |
| TC7 | (6,2) | y的最小值+1 | 测试y接近最小值时的函数行为 |
| TC8 | (6,30) | y的最大值-1 | 测试y接近最大值时的函数行为 |
| TC9 | (6,31) | y的最大值 | 测试y取最大值时的函数行为 |
四、实验思考
1、在实际的测试中,如何设计测试用例才能达到用最少的测试用例检测出最多的缺陷;
通过综合运用系统化测试方法、优先覆盖高风险区域、优化用例结构、结合经验推测、利用自动化工具并持续迭代,可设计出高效的测试用例集,以最少的用例检测出最多的缺陷。关键在于平衡测试覆盖度和测试效率,确保测试用例针对最可能出现问题的场景。
2、在进行用例设计时,如何考虑软件测试用例的充分性和减少软件测试用例的冗余性;
测试用例的充分性和冗余性是相互矛盾又相互依存的关系。通过系统化的测试方法、覆盖关键场景、利用覆盖率指标确保充分性,同时通过优化用例设计、定期评审、自动化测试减少冗余性,可以达到测试效率与测试质量的平衡。在实际项目中,需要根据项目的时间、资源和风险等级灵活调整测试策略,确保测试用例既全面又高效。
3、本次实验遇到的难点、如何解决的及体会。
- 日期处理中的时区问题
难点:在实现日期转星期几功能时,不同时区可能导致日期计算不准确。
解决方法:使用UTC时间创建日期对象(new Date(dateStr + 'T00:00:00Z')),避免时区影响,确保计算结果的一致性。 - 用户输入格式的处理
难点:用户输入的日期格式可能不规范(如2026-4-8),导致程序无法正确解析。
解决方法:添加自动补全功能,使用padStart方法为月份和日期补全前导零,确保格式统一。 - 找零钱算法的设计
难点:如何确保找零的货币张数最少。
解决方法:采用贪心算法,从最大面值开始,尽可能多地使用大面值货币,然后依次使用较小面值的货币。 - 输入验证与错误处理
难点:需要处理各种无效输入情况,如非数字、超出范围等。
解决方法:添加全面的输入验证,对不同类型的错误提供明确的错误提示,确保程序的健壮性。
体会:
代码设计的重要性:良好的代码结构和设计模式能大大提高代码的可读性和可维护性。例如,将输入验证、业务逻辑和用户交互分离,使代码更加清晰。
测试的必要性:通过系统化的测试方法,可以发现代码中潜在的问题,确保功能的正确性。特别是边界情况和异常输入的处理,是测试的重点。
用户体验的考虑:在设计程序时,不仅要实现功能,还要考虑用户的使用体验。例如,对用户输入进行容错处理,提供友好的错误提示,使程序更加用户友好。

浙公网安备 33010602011771号