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是一个由三个变量(月份、日期和年份)的函数。函数返回输入日期后边的那个日期。
作为输入:变量月份、日期和年都具有整数值,满足以下条件。
C1:1<=月份<=12
C2:1<=日期<=31
C3:1912<=年<=2050
要求学生能够理解基于决策表的测试方法的相关概念、方法和过程。
每组二到四人,根据实验题目编写出对应的c语言或c++语言程序,组间相互交换程序,按黑盒测试的方法进行测试。
本次软件测试过程当中,使用了JUnit框架,将相关的测试数据保存在csv数据文件当中,通过对csv数据文件读取测试用例来进行测试,方便我们修改测试用例,而且可以降低代码的复杂度、提高代码的可阅读性。
三角形问题:
决策表:
1-32 | 33-48 | 48-56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | |
---|---|---|---|---|---|---|---|---|---|---|---|
C1:a<b+c? | F | T | T | T | T | T | T | T | T | T | T |
C2:b<a+c? | - | F | T | T | T | T | T | T | T | T | T |
C3:c<a+b? | - | - | F | T | T | T | T | T | T | T | T |
C4:a=b? | - | - | - | T | T | T | T | F | F | F | F |
C5:a=c? | - | - | - | T | T | F | F | T | T | F | F |
C6:b=c? | - | - | - | T | F | T | F | T | F | T | F |
A1:非三角形 | √ | √ | √ | ||||||||
A2:不等边三角形 | √ | ||||||||||
A3:等腰三角形 | √ | √ | √ | ||||||||
A4:等边三角形 | √ | ||||||||||
A5:不可能 | √ | √ | √ |
测试用例:
用例 | a | b | c | 预期输出 |
---|---|---|---|---|
DT1 | 2 | 1 | 1 | 非三角形 |
DT2 | 2 | 4 | 1 | 非三角形 |
DT3 | 2 | 3 | 7 | 非三角形 |
DT4 | 2 | 2 | 2 | 等边三角形 |
DT5 | ? | ? | ? | 不可能 |
DT6 | ? | ? | ? | 不可能 |
DT7 | 3 | 3 | 4 | 等腰三角形 |
DT8 | ? | ? | ? | 不可能 |
DT9 | 3 | 4 | 3 | 等腰三角形 |
DT10 | 4 | 3 | 3 | 等腰三角形 |
DT11 | 3 | 4 | 5 | 不等边三角形 |
NextData问题:
等价类划分:
M1 ={月份:每月有30天}
M2 ={月份:每月有31天,12月除外}
M3 ={月份:此月是12月}
M4 ={月份:此月是2月}
D1 ={日期:1<=日期<=27}
D2 ={日期:日期=28}
D3 ={日期:日期=29}
D4 ={日期:日期=30}
D5 ={日期:日期=31}
Y1 ={年:是闰年}
Y1 ={年:是平年}
决策表:
1-3 | 4 | 5 | 6-9 | 10 | 11-14 | 15 | 16 | 17 | 18 | 19 | 20 | 21-22 | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|
C1:月份在 | M1 | M1 | M1 | M2 | M2 | M3 | M3 | M4 | M4 | M4 | M4 | M4 | M4 |
C2:日在 | D1,D2,D3 | D4 | D5 | D1,D2,D3,D4 | D5 | D1,D2,D3,D4 | D5 | D1 | D2 | D2 | D3 | D3 | D4,D5 |
C3:年在 | - | - | - | - | - | - | - | - | Y1 | Y2 | Y1 | Y2 | - |
A1:不可能 | √ | √ | √ | ||||||||||
A2:日期加1 | √ | √ | √ | √ | √ | ||||||||
A3:日期复位 | √ | √ | √ | √ | √ | ||||||||
A4:月加1 | √ | √ | √ | √ | |||||||||
A5:月复位 | √ | ||||||||||||
A6:年加1 | √ |
测试用例:
用例 | 年 | 月份 | 日期 | 预期输出 |
---|---|---|---|---|
DT1 | 2001 | 6 | 15 | 2001/6/16 |
DT2 | 2001 | 6 | 30 | 2001/7/1 |
DT3 | 2001 | 6 | 31 | 日数不合实际 |
DT4 | 2001 | 5 | 15 | 2001/5/16 |
DT5 | 2001 | 5 | 31 | 2001/6/1 |
DT6 | 2001 | 12 | 15 | 2001/12/16 |
DT7 | 2001 | 12 | 31 | 2002/1/1 |
DT8 | 2001 | 2 | 15 | 2001/2/16 |
DT9 | 2004 | 2 | 28 | 2004/2/29 |
DT10 | 2001 | 2 | 28 | 2001/3/1 |
DT11 | 2004 | 2 | 29 | 2004/3/1 |
DT12 | 2001 | 2 | 29 | 日数不合实际 |
DT13 | 2001 | 2 | 30 | 日数不合实际 |
【测试结果及分析】
三角形问题:
本次实验中由于在设计测试用例时出现了输入用例为“? ? ?”的情况,而原本的程序在读入测试用例数据时又只能识别数字类型的数据,导致三组“? ? ?”测试用例在程序首次运行时出现了报错情况。所以本次的三角形问题程序与前两次的程序相比多加了一个isNumberical方法来判断输入数据是否为数字类型,且更换了问题的程序流程图,较之先前的代码更加的全面与详细。
关于结果的分析,在本次实验中,所有输入数据中存在非数字类型的测试用例都会输出“不可能”的结果;所有不能构成三角形问题的用例都会输出“非三角形”;其余所有能够成三角形的都会被程序判断并输出其类型。
NextData问题:
本次实验中,NextDate问题的测试程序与之前实验中的基本一致,发生了主要变化的部分是测试用例的设计部分,明显的,本次实验的测试用例较之之前少了很多,但与之对应的是设计部分增加的工作量,即:设计部分付出的工作量与测试用例的数量两者之间大致成反比。
本次实验中,可以发现两个问题在解决的过程中都采取了类似于等价类划分的方法划分了条件桩,本实验中的每个条件桩都只有true和false两种可能,但即便如此,在三角形问题中所产生的条目数量都在急剧地增加。但在第二个问题中,由于在设计时根据年月日之间存在着的一定制约关系,最终产生的条目数要少很多,可见条件项之间的制约关系有时也可以减少测试人员所编写的用例数量。
在编写代码的过程中,可以发现程序逻辑为if-else if-else的代码十分适合决策表分析法的使用,这一点在条件桩的结果只有两种情况时更为明显。其次,本实验中条件的排列顺序与规则的排列顺序对于决策表的使用都没有影响,这是极为理想的状态,适用于使用决策表。
三角形问题源码:
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.CsvFileSource;
import java.util.Objects;
/**
* @author MaxBrooks chentingxian195467@163.com
* @version 2022/10/25 19:47
* @since JDK17
*/
class TriangleTest {
/**
* 判断是否是数字
* @param a 参数a
* @param b 参数b
* @param c 参数c
* @return boolean
*/
static boolean isNumerical(String a, String b, String c){
return !Objects.equals(a, "?") && !Objects.equals(b, "?") && !Objects.equals(c, "?");
}
/**
* 判断是否输入数据是否合法,若合法,返回true,反之返回false
* @param a 边1
* @param b 边2
* @param c 边3
* @return 返回判断值
*/
static boolean isDataUseful(Integer a, Integer b,Integer c){
return (a >= 1 && a <= 100) && (b >= 1 && b <= 100) && (c >= 1 && c <= 100);
}
/**
* 判断输入数据能否构成三角形,若能,返回true,反之返回false
* @param a 边1
* @param b 边2
* @param c 边3
* @return 返回判断值
*/
static boolean isTriangle(Integer a, Integer b,Integer c){
return !(a + b <= c) && !(b + c <= a) && !(a + c <= b);
}
/**
* 判断三角形类型
* @param a 边1
* @param b 边2
* @param c 边3
*/
static void kindOfTriangle(Integer a, Integer b, Integer c){
if (a.equals(b) || b.equals(c) || a.equals(c)){
if (a.equals(b) && b.equals(c)) //没必要再添一句a.equals(c),因为前两者的可以推导出a == c的结论
System.out.println("等边三角形");
else
System.out.println("等腰三角形");
}else
System.out.println("不等边三角形");
}
@ParameterizedTest
@CsvFileSource(resources = "/softwarequalityandtest/DecisionTable/trianglesForDT.csv")
void isTriangle02(String a, String b,String c){
System.out.println("***************************");
System.out.printf("%3s %3s %3s ",a,b,c);
if (isNumerical(a, b, c)){
Integer x = Integer.valueOf(a);
Integer y = Integer.valueOf(b);
Integer z = Integer.valueOf(c);
if (isDataUseful(x, y, z)){
if (isTriangle(x, y, z)){
kindOfTriangle(x, y, z);
}else
System.out.println("非三角形");
}else {
System.out.println("非三角形");
}
}else
System.out.println("不可能");
}
}
NextDate问题源码:
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.CsvFileSource;
/**
* @author MaxBrooks chentingxian195467@163.com
* @version 2022/10/25 19:47
* @since JDK17
*/
class NextDateTest {
/**
* 判断单个输入值是否合法:
* 是 -> true
* 否 -> false
* @param yyyy 年
* @param MM 月
* @param dd 日
* @return 单个输入值是否合法
*/
static boolean isSingleInputDataUseful(Integer yyyy, Integer MM, Integer dd){
return (yyyy >= 1912 && yyyy <= 2050) && (MM >= 1 && MM <= 12) && (dd >= 1 && dd <= 31);
}
/**
* 判断是否为闰年
* @param yyyy 年份
* @return 若为闰年 -> true
*/
static boolean isLeapYear(Integer yyyy){
return (yyyy % 400 == 0) || (yyyy % 4 == 0 && yyyy % 100 != 0);
}
@ParameterizedTest
@CsvFileSource(resources = "/softwarequalityandtest/DecisionTable/nextdateForDT.csv")
void nextDate(Integer yyyy, Integer MM,Integer dd){
if (!isSingleInputDataUseful(yyyy, MM, dd)){
System.out.println("************************************");
System.out.printf("当前日期为%4d/%2d/%2d 输入数据不合法\n",yyyy,MM,dd);
}else{
//一个标志,若为真,则说明当前月的最大日数比输入的要小,输入值有问题
boolean dayFlag = false;
switch (MM){
case 1:
case 3:
case 5:
case 7:
case 8:
case 10:
if (dd == 31){
dd = 1;
MM = MM + 1;
}else {
dd += 1;
}
break;
case 4:
case 6:
case 9:
case 11:
if (dd == 30){
dd = 1;
MM += 1;
} else if (dd == 31) {
dayFlag = true; //输入日期超出当前月的实际最大值
}else
dd += 1;
break;
case 2:
if (isLeapYear(yyyy)){ //闰年
if (dd == 29){
dd = 1;
MM = 3;
} else if (dd < 29) {
dd += 1;
}else
dayFlag = true; //输入日期超出当前月的实际最大值
}else { //平年
if (dd == 28){
dd = 1;
MM = 3;
}else if (dd < 28){
dd += 1;
}else
dayFlag = true; //输入日期超出当前月的实际最大值
}
break;
case 12:
if (dd == 31){
dd = 1;
MM = 1;
yyyy += 1;
}else {
dd += 1;
}
break;
default:
}
if (dayFlag){
System.out.println("************************************");
System.out.printf("当前日期为%4d/ %2d/ %2d 日数不合实际\n",yyyy,MM,dd);
}else {
System.out.println("************************************");
System.out.printf("次日日期为%4d/ %2d/ %2d 测试通过\n",yyyy,MM,dd);
}
}
}
}