【实验环境】
Windows 10 操作系统, C,C++,C#、Java或Python语言开发环境(IDE)。
【实验类型】
设计型
【实验目的】
- 认识黑盒测试方法中等价类划分测试方法原理
- 掌握黑盒测试方法中等价类划分测试方法过程
【实验内容】
- 三角形问题
问题描述:三角形问题接受三个整数,a、b和c作为输入,用作三角形的边。程序的输出是由这三条边确定的三角形类型:等边三角形、等腰三角形、不等边三角形或非三角形。
作为输入:三角形的三条边必须满足如下条件:
C1:1<=a<=100
C2:1<=b<=100
C3:1<=c<=100
C4:a<b+c
C5:b<a+c
C6:c<a+b
- NextDate函数
问题描述:NextDate是一个由三个变量(月份、日期和年份)的函数。函数返回输入日期后边的那个日期。
作为输入:变量月份、日期和年都具有整数值,满足以下条件。
C1:1<=月份<=12
C2:1<=日期<=31
C3:1912<=年<=2050
- 佣金问题
问题描述:前亚利桑那洲境内的一位步枪销售商销售密苏里州制造商制造的步枪机(lock)、枪托(stock)和枪管(barrel)。
枪机卖45美元,枪托卖30美元,枪管卖25美元。
销售商每月至少要售出一支完整的步枪,
且生产限额是大多数销售商在一个月内可销售70个枪机、80个枪托和90个枪管。
每访问一个镇子后,销售商都给密苏里州步枪制造商发出一份很短的电报,通知几个枪机、枪托、枪管被售出。这样步枪制造商就知道当月的销售情况,并计算销售商的佣金如下:
不到(含)1000美元的部分为10%;
1000(不含)~1800(含)美元的部分为15%;
超过1800美元的部分为20%。
佣金程序生成月份销售报告,汇总售出的枪机、枪托和枪管总数,销售商的总销售额以及佣金。
【算法描述】
程序1算法描述:
1. 输入三个整数a、b和c,代表三角形的三条边。
2. 首先,检查输入的a、b和c是否在范围1到100内(满足条件C1到C3)。
3. 接下来,检查是否满足三角形的边长条件(满足条件C4到C6):
- 检查是否a + b > c
- 检查是否a + c > b
- 检查是否b + c > a
4. 如果满足上述条件,进一步判断三角形的类型:
- 如果a、b和c都相等,输出"等边三角形"。
- 否则,如果至少两个边相等,输出"等腰三角形"。
- 否则,输出"不等边三角形"。
5. 如果不满足条件4,输出"非三角形"。
程序2算法描述:
1. 输入三个整数,分别表示月份(month)、日期(day)和年份(year)。
2. 首先,检查输入日期是否符合以下条件(条件C1到C3):
- 1 <= month <= 12
- 1 <= day <= 31
- 1912 <= year <= 2050
3. 如果输入日期不符合条件,输出 "输入日期不符合条件",并结束算法。
4. 否则,进入下一个日期计算部分。
5. 增加日期(day)的值 by 1。
6. 检查日期是否超过了一个月的天数:
- 如果 day > 31,表示下一个月的第一天,day 被设置为 1,然后 month 的值增加 by 1。
- 如果 day > 30,而当前月份是4、6、9或11,同样 day 被设置为 1,month 的值增加 by 1。
- 如果 day > 29,当前月份为2,且 year 为闰年,同样 day 被设置为 1,month 的值增加 by 1。
- 如果 day > 28,当前月份为2,但 year 不是闰年,同样 day 被设置为 1,month 的值增加 by 1。
7. 继续检查月份,如果 month 超过 12,表示下一年的第一月,month 被设置为 1,year 的值增加 by 1。
8. 输出下一个日期的月份、日期和年份。
程序3算法描述:
1.输入:输入为售出的枪机(`locks`)、枪托(`stocks`)、和枪管(`barrels`)的数量。
2.计算销售额:使用每个部件的售价(`lock_price = 45`,`stock_price = 30`,`barrel_price = 25`),计算总销售额:
3. 计算总售出步枪数量:从售出的枪机、枪托、和枪管中选择最小值,表示可以组装的完整步枪数量:
4. 确定佣金率:根据总销售额确定佣金率:
- 不到1000美元的部分为10%
- 1000美元到1800美元的部分为15%
- 超过1800美元的部分为20%
5. 计算佣金:使用佣金率计算佣金:
6. 输出结果:打印月度销售报告,包括售出的枪机、枪托、枪管数量,总售出步枪数量,总销售额,佣金率和佣金。
【测试用例】
1.三角形问题
(1)输入域
划分等价类
输入值 | 有效等价类 | 无效等价类 |
a | 1≤a≤100 | a<1 |
a>100 | ||
b | 1≤b≤100 | b<1 |
b>100 | ||
c | 1≤c≤100 | c<1 |
c>100 |
弱/强一般等价类测试
测试序号 | a | b | c | 预期结果 | 输出结果 |
SN1 | 3 | 4 | 5 | 不等边三角形 | 不等边三角形 |
弱健壮等价类测试
测试序号 | a | b | c | 预期结果 | 输出结果 |
WN1 | 3 | 4 | 5 | 不等边三角形 | 不等边三角形 |
WR1 | -1 | 50 | 50 | 输入不合法 | 输入不合法 |
WR2 | 50 | -1 | 50 | 输入不合法 | 输入不合法 |
WR3 | 50 | 50 | -1 | 输入不合法 | 输入不合法 |
WR4 | 101 | 50 | 50 | 输入不合法 | 输入不合法 |
WR5 | 50 | 101 | 50 | 输入不合法 | 输入不合法 |
WR6 | 50 | 50 | 101 | 输入不合法 | 输入不合法 |
强健壮等价类测试(3^3=27个)
测试编号 | a | b | c | 预期结果 | 实际输出 |
| -1 | -1 | -1 | 输入不合法 | 输入不合法 |
| -1 | -1 | 50 | 输入不合法 | 输入不合法 |
| -1 | -1 | 101 | 输入不合法 | 输入不合法 |
| -1 | 50 | -1 | 输入不合法 | 输入不合法 |
| -1 | 50 | 50 | 输入不合法 | 输入不合法 |
| -1 | 50 | 101 | 输入不合法 | 输入不合法 |
| -1 | 101 | -1 | 输入不合法 | 输入不合法 |
| -1 | 101 | 50 | 输入不合法 | 输入不合法 |
| -1 | 101 | 101 | 输入不合法 | 输入不合法 |
| 50 | -1 | -1 | 输入不合法 | 输入不合法 |
| 50 | -1 | 50 | 输入不合法 | 输入不合法 |
| 50 | -1 | 101 | 输入不合法 | 输入不合法 |
| 50 | 50 | -1 | 输入不合法 | 输入不合法 |
| 50 | 50 | 50 | 等边三角形 | 等边三角形 |
| 50 | 50 | 101 | 输入不合法 | 输入不合法 |
| 50 | 101 | -1 | 输入不合法 | 输入不合法 |
| 50 | 101 | 50 | 输入不合法 | 输入不合法 |
| 50 | 101 | 101 | 输入不合法 | 输入不合法 |
| 101 | -1 | -1 | 输入不合法 | 输入不合法 |
| 101 | -1 | 50 | 输入不合法 | 输入不合法 |
| 101 | -1 | 101 | 输入不合法 | 输入不合法 |
| 101 | 50 | -1 | 输入不合法 | 输入不合法 |
| 101 | 50 | 50 | 输入不合法 | 输入不合法 |
| 101 | 50 | 101 | 输入不合法 | 输入不合法 |
| 101 | 101 | -1 | 输入不合法 | 输入不合法 |
| 101 | 101 | 50 | 输入不合法 | 输入不合法 |
| 101 | 101 | 101 | 输入不合法 | 输入不合法 |
(2)输出域
划分等价类
R1={<a,b.c>:有三条边a、b和c的等边三角形}
R2={<a, b.c>:有三条边a、b和c的等腰三角形}
R3={<a. b.c>:有三条边a、b和c的不等边三角形}
R4={<a. b. c>;有三条边a、b和c不构成三角形}
弱/强一般等价类测试
测试序号 | a | b | c | 预期结果 | 输出结果 |
| 50 | 50 | 50 | 等边三角形 | 等边三角形 |
| 50 | 50 | 40 | 等腰三角形 | 等腰三角形 |
| 30 | 40 | 50 | 不等边三角形 | 不等边三角形 |
| 30 | 10 | 50 | 非三角形 | 非三角形 |
2.Nextdate函数
划分等价类
三个变量的取值范围:
C1: 1 ≤ month ≤ 12
C2: 1 ≤ day ≤ 31
C3: 1912 ≤ year ≤ 2050
可以划分为以下等价类集合:
M1 = {month: month has 30 days}
M2 = {month: month has 31 days except December}
M3 = {month: month is December}
M4 = {month: month is February}
D1 = {day: 1 ≤ day ≤ 27}
D2 = {day: day = 28}
D3 = {day: day = 29}
D4 = {day: day = 30}
D5 = {day: day = 31}
Y1 = {year: year is a leap year}
Y2 = {year: year is a common year}
可划分为10个弱一般等价类(除去了无效的等价类),为其设计测试用例如下表格所示
R1 = {M1, {D1, D2, D3}, {Y1, Y2}}
R2 = {M1, D4, {Y1, Y2}}
R3 = {M2, {D1, D2, D3, D4}, {Y1, Y2}}
R4 = {M2, D5, {Y1, Y2}}
R5 = {M3, {D1, D2, D3, D4}, {Y1, Y2}}
R6 = {M3, D5, {Y1, Y2}}
R7 = {M4, D1, {Y1, Y2}}
R8 = {M4, D2, Y1}
R9 = {M4, D2, Y2}
R10 = {M4, D3, Y1}
弱一般等价类测试用例
月份 | 日期 | 年 | 预期输出 | 实际输出 |
6 | 15 | 1912 | 1912年6月16日 | 6/16/1912 |
强一般等价类测试用例
月份 | 日期 | 年份 | 预期输出 | 实际输出 |
6 | 15 | 1912 | 1912年6月16日 | 6/16/1912 |
弱健壮等价类测试用例
用例 | 描述 | 月份 | 日期 | 年 | 预期输出 | 实际输出 |
WR1 | 对“年”进行弱健壮等价类 | 6 | 15 | 1912 | 1912年6月16日 | 6/16/1912 |
WR2 | 0 | 1 | 1912 | 月份不在1~12中 | 输入日期不符合条件 | |
WR3 | 15 | 1 | 1912 | 月份不在1~12中 | 输入日期不符合条件 | |
WR4 | 1 | 0 | 1912 | 日期不在1~31中 | 输入日期不符合条件 | |
WR5 | 1 | 32 | 1912 | 日期不在1~31中 | 输入日期不符合条件 | |
WR6 | 对“月份”进行弱健壮等价类 | 1 | 1 | 1911 | 年不在1912~2050中 | 输入日期不符合条件 |
WR7 | 1 | 1 | 2051 | 年不在1912~2050中 | 输入日期不符合条件 |
强健壮等价类测试用例
用例 | 描述 | 月份 | 日期 | 年 | 预期输出 | 实际输出 |
SR1 | 对“年”进行强健壮等价类测试用例 | 15 | 1 | 1912 | 月份不在1~12中 | 输入日期不符合条件 |
SR2 | 1 | 32 | 1912 | 日期不在1~31中 | 输入日期不符合条件 | |
SR3 | 0 | 0 | 1912 | 两个无效一个有效 | 输入日期不符合条件 | |
SR4 | 1 | 1 | 1911 | 年份不在1912~2050中 | 输入日期不符合条件 | |
SR5 | 0 | 1 | 1911 | 两个无效一个有效 | 输入日期不符合条件 | |
SR6 | 1 | 0 | 1911 | 两个无效一个有效 | 输入日期不符合条件 | |
SR7 | 0 | 0 | 1911 | 三个无效 | 输入日期不符合条件 |
3.佣金问题
(1)输入域
输入变量的有效类:
L1={枪机:1≤枪机≤70}
S1={枪托:1≤枪托≤80}
B1={枪管:1≤枪管≤90)
输入变量的无效类:
L2={枪机:枪机<1}
L3={枪机:枪机>70}
S2={枪托:枪托<1}
S3={枪托:枪托>80}
B2={枪管:枪管<1}
B3={枪管:枪管>90}
弱/强一般等价类测试用例
枪机 | 枪托 | 枪管 | 预期输出 | 实际输出 |
50 | 60 | 70 | 1020 | 1020 |
弱健壮等价类测试用例
测试用例 | 枪机 | 枪托 | 枪管 | 预期输出 | 实际输出 |
WN1 | 50 | 60 | 70 | 1020 | 1020 |
WR1 | -1 | 60 | 70 | 输入不合法 | 输入不合法 |
WR2 | 50 | 0 | 70 | 未达标 | 未达标 |
WR3 | 50 | 60 | -10 | 输入不合法 | 输入不合法 |
WR4 | 80 | 60 | 70 | 超额 | 超额 |
WR5 | 50 | 99 | 70 | 超额 | 超额 |
WR6 | 50 | 60 | 1000 | 超额 | 超额 |
强健壮等价类测试用例
测试用例 | 描述 | 枪机 | 枪托 | 枪管 | 预期输出 | 实际输出 |
| 对L、S进行强健壮等价类测试 | -1 | 0 | 0 | 输入不合法 | 未达标 |
| -1 | -10 | 70 | 输入不合法 | 输入不合法 | |
| -1 | -1 | 91 | 输入不合法 | 超额 | |
| -1 | 50 | 0 | 输入不合法 | 未达标 | |
| -1 | 1 | 70 | 输入不合法 | 输入不合法 | |
| 0 | 80 | 91 | 未达标 | 未达标 | |
| 0 | 81 | 0 | 未达标 | 未达标 | |
| 0 | 99 | 70 | 未达标 | 未达标 | |
| 0 | 100 | 91 | 未达标 | 未达标 | |
| 对B、S进行强健壮等价类测试 | 50 | 0 | 0 | 未达标 | 未达标 |
| 50 | -10 | 70 | 输入不合法 | 输入不合法 | |
| 50 | -1 | 91 | 输入不合法 | 超额 | |
| 50 | 50 | 0 | 未达标 | 未达标 | |
| 50 | 1 | 70 | 666 | 666 | |
| 50 | 80 | 91 | 超额 | 超额 | |
| 50 | 81 | 0 | 未达标 | 未达标 | |
| 50 | 99 | 70 | 超额 | 超额 | |
| 50 | 100 | 91 | 超额 | 超额 | |
| 对L、B进行强健壮等价类测试 | 71 | 0 | 0 | 超额 | 未达标 |
| 75 | -10 | 70 | 超额 | 超额 | |
| 79 | -1 | 91 | 超额 | 超额 | |
| 99 | 50 | 0 | 超额 | 未达标 | |
| 99 | 1 | 70 | 超额 | 超额 | |
| 99 | 80 | 91 | 超额 | 超额 | |
| 99 | 81 | 0 | 超额 | 未达标 | |
| 156 | 99 | 70 | 超额 | 超额 | |
| 500 | 100 | 91 | 超额 | 超额 |
- 输出域
等价类划分:
销售额=45×枪机数+30×枪托数+25×枪管数佣金
值域定义三个变量的等价类:
S1 ={<枪机,枪托,枪管>:销售额≤1000}
S2 ={<枪机,枪托,枪管>:1000<销售额≤1800)
S3 ={<枪机,枪托,枪管>:销售额>1800}
弱一般等价类测试
测试序号 | 枪机 | 枪托 | 枪管 | 销售额 | 预期输出 | 实际输出 |
| 5 | 5 | 5 | 500 | 50 | 50 |
| 15 | 15 | 15 | 1500 | 175 | 175 |
| 30 | 40 | 50 | 3800 | 620 | 620 |
【实验总结】
1.在具体进行测试时,等价类测试和健壮性测试都有不同的作用,随着测试复杂程度的提升,程序出错的可能性也就越小。
2.在设计数据范围时,要结合现实条件设计,比如第一个实验中没有考虑输入字符,在实际使用中就可能出现问题
【附-程序源码】
- 三角形问题
#include <iostream>
using namespace std;
int main() {
int a, b, c;
while (
cin >> a >> b >> c) {
if (a >= 1 && b >= 1 && c >= 1 && a <= 100 && b <= 100 && c <= 100) {
if (a + b > c && a + c > b && b + c > a) {
if (a == b && b == c) {
cout << "等边三角形" << endl;
} else if (a == b || b == c || a == c) {
cout << "等腰三角形" << endl;
} else {
cout << "不等边三角形" << endl;
}
} else {
cout << "非三角形" << endl;
}
} else {
cout << "输入不合法" << endl;
}
}
return 0;
}
2.NextDate函数
#include <iostream>
using namespace std;
bool IsLeapYear(int year) {
if ((year % 4 == 0 && year % 100 != 0) || (year % 400 == 0)) {
return true;
} else {
return false;
}
}
bool IsValidDate(int month, int day, int year) {
if (month < 1 || month > 12 || day < 1 || day > 31 || year < 1912 || year > 2050) {
return false;
}
if (month == 4 || month == 6 || month == 9 || month == 11) {
return (day <= 30);
} else if (month == 2) {
if (IsLeapYear(year)) {
return (day <= 29);
} else {
return (day <= 28);
}
} else {
return true;
}
}
void NextDate(int &month, int &day, int &year) {
day++;
if (day > 31 || (day > 30 && (month == 4 || month == 6 || month == 9 || month == 11)) ||
(day > 29 && month == 2 && IsLeapYear(year)) || (day > 28 && month == 2)) {
day = 1;
month++;
}
if (month > 12) {
month = 1;
year++;
}
}
int main() {
int month, day, year;
while(cin >> month >> day >> year){ // 以空格分隔输入
if (!IsValidDate(month, day, year)) {
cout << "输入日期不符合条件" << endl;
continue;
}
NextDate(month, day, year);
cout << month << "/" << day << "/" << year << endl;
}
return 0;
}
3.佣金问题
# 定义每个部件的售价
lock_price = 45
stock_price = 30
barrel_price = 25
def calculate_commission(locks, stocks, barrels):
# 计算销售额
total_sales = locks * lock_price + stocks * stock_price + barrels * barrel_price
# 计算佣金
if total_sales <= 1000:
commission = total_sales * 0.1
elif total_sales <= 1800:
commission = 100+(total_sales-1000) * 0.15
else:
commission = 220+ (total_sales-1800) * 0.2
# 打印月度销售报告
print("月度销售报告:")
print(f"枪机数量: {locks}", end=" ")
print(f"枪托数量: {stocks}", end=" ")
print(f"枪管数量: {barrels}")
print(f"总销售额: ${total_sales}", end=" ")
print(f"佣金: ${commission}")
while True:
locks, stocks, barrels = map(int, input().split())
if locks == 0 or stocks == 0 or barrels == 0:
print("未达标")
continue
elif locks > 70 or stocks > 80 or barrels > 90:
print("超额")
continue
elif locks > 0 and stocks > 0 and barrels > 0:
calculate_commission(locks, stocks, barrels)
else:
print("输入不合法")
continue