【软件工程】黑盒测试——边界值分析法

实验一 黑盒测试——边界值分析法


图:封面

【开发语言及实现平台或实验环境】

开发语言:Java
实验平台:Windows10, Intellij IDEA

【实验目的】

  1. 认识黑盒测试方法中边界值分析测试法原理
  2. 掌握黑盒测试方法中边界值分析测试法过程

【实验要求】

  1. 要求学生能够理解黑盒测试的边界值测试方法相关概念和测试的过程、 方法。
  2. 理解健壮性测试的概念。

【实验原理】

对编写的实验内容,采用边界值分析黑盒测试法进行黑盒测试。

【实验材料】

  1. 三角形问题
    问题描述:三角形问题接受三个整数,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

  2. NextDate 函数
    问题描述:NextDate 是一个由三个变量(月份、日期和年份)的函数。
    函数返回输入日期后边的那个日期。 作为输入:变量月份、日期和年都具有整数值,满足以下条件。
    C1:1<=月份<=12
    C2:1<=日期<=31
    C3:1912<=年<=2050

【实验步骤】

  1. 预习相关课堂和实验内容,了解测试对象。 2. 编写实验材料源代码。
  2. 设计测试用例。
  3. 根据问题需要建立桩模块和驱动模块。、
  4. 测试。
  5. 填写试验报告。

    【实验代码】

三角形问题

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
package procs;

import java.util.InputMismatchException;
import java.util.Scanner;

public class TriangleProc {

public int sideA = 0;
public int sideB = 0;
public int sideC = 0;

public TriangleProc() {

}

/**
* 函数:验证三角形边的长度范围
*
* @param side
* @return
*/
public boolean verifyLengthRange(int side) {
if ((side >= 1) && (side <= 100)) {
return true;
} else {
System.out.println(String.format("边长 %1d 不满足大于等于1且小于等于 100", side));
System.out.println("=========请重新输入=========");
return false;
}

}

/**
* 函数:验证三角形两边之和大于第三边
*
* @param triangleProc
* @return
*/
public boolean verifyFormPrinciple(TriangleProc triangleProc) {

if ((triangleProc.sideA + triangleProc.sideB <= triangleProc.sideC)
|| (triangleProc.sideA + triangleProc.sideC <= triangleProc.sideB)
|| (triangleProc.sideB + triangleProc.sideC <= triangleProc.sideA)) {
System.out.println(String.format("边长组合为 %1d %2d %3d不满足两边之和大于第三边,是非三角形",
triangleProc.sideA, triangleProc.sideB, triangleProc.sideC));
System.out.println("=========请重新输入=========");
return false;
} else {
System.out.println("边长组合满足两边之和大于第三边");
return true;
}
}


public String judgeTriangleType(TriangleProc triangleProc) {
if (triangleProc.sideA == triangleProc.sideB || triangleProc.sideA == triangleProc.sideC
|| triangleProc.sideB == triangleProc.sideC) {
if (triangleProc.sideA == triangleProc.sideB && triangleProc.sideB == triangleProc.sideC) {
String triangleType = "等边三角形";
return triangleType;
} else {
String triangleType = "等腰三角形";
return triangleType;
}
} else {
String triangleType = "非等边三角形";
return triangleType;
}
}

public void inputEdge(Scanner scanner, TriangleProc triangleProc) {
int tempSideA = 0;
int tempSideB = 0;
int tempSideC = 0;

// System.out.println("Welcome to triangle judge program!!!d");
System.out.println("Please input the side A");

if (scanner.hasNext()) {
tempSideA = scanner.nextInt();
triangleProc.sideA = tempSideA;
System.out.println(String.format("Edge A is %1d. Please input side B", tempSideA));
tempSideB = scanner.nextInt();
triangleProc.sideB = tempSideB;
System.out.println(String.format("Edge B is %1d. Please input side C", tempSideB));
tempSideC = scanner.nextInt();
triangleProc.sideC = tempSideC;
System.out.println(String.format("Edge C is %1d. The input is finished\n\n", tempSideC));

}

boolean stopFlag = false;

while (!stopFlag) {
if (verifyLengthRange(triangleProc.sideA) && verifyLengthRange(triangleProc.sideB)
&& verifyLengthRange(triangleProc.sideC)) {
if (verifyFormPrinciple(triangleProc)) {
stopFlag = true;
String triangleType = judgeTriangleType(triangleProc);
System.out.println(String.format("你输入的三角形类型为:%1s", triangleType));
System.out.println("========The End========");
} else {
inputEdge(scanner, triangleProc);
}

} else {
// 边长不满足两个条件,重新输入
inputEdge(scanner, triangleProc);
}
}
}


/**
* 主函数,同时也是测试函数
*
* @param args
*/
public static void main(String[] args) {
TriangleProc triangleProc = new TriangleProc();
Scanner scanner = new Scanner(System.in);
triangleProc.inputEdge(scanner, triangleProc);

}

}

运行示例

NextDate

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
package procs;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.Scanner;

public class NextDate {
int year = 0;
int month = 0;
int day = 0;

private String nextDateFunction(int year, int month, int day){

Calendar calendar = Calendar.getInstance();

String yearString = Integer.toString(year);
String monthString = Integer.toString(month);
String dayString = Integer.toString(day);

String stringDate = yearString + '-' + monthString + '-' + dayString;

Date date = null;
try {
date = new SimpleDateFormat("yyyy-MM-dd").parse(stringDate);
} catch (ParseException e) {
e.printStackTrace();
}

calendar.setTime(date);

int dayBefore = calendar.get(Calendar.DATE);
calendar.set(Calendar.DATE, dayBefore + 1);

String dayAfter = new SimpleDateFormat("yyyy-MM-dd").format(calendar.getTime());
return dayAfter;

}


private void dateCheckFunction(Scanner scanner, NextDate nextDate) {
System.out.println("Please Input Your Specific Day");

do {
System.out.println("Please Input the Year(1912 <= year <= 2050): ");
nextDate.year = scanner.nextInt();
} while (nextDate.year < 1912 || nextDate.year > 2050);

do {
System.out.println("Please Input the Month(1 <= month <= 12): ");
nextDate.month = scanner.nextInt();
} while (nextDate.month < 1 || nextDate.month > 12);

do {
System.out.println("Please Input the Day(1 <= day <= 31): ");
nextDate.day = scanner.nextInt();
} while (nextDate.day < 1 || nextDate.day > 31);

}

public static void main(String[] args) {

Scanner scanner = new Scanner(System.in);

NextDate nextDate = new NextDate();

// 检查输入的日期是否符合要求
nextDate.dateCheckFunction(scanner, nextDate);

// 根据nextDateFunction函数获取后一天的日期
String dayAfter = nextDate.nextDateFunction(nextDate.year, nextDate.month, nextDate.day);

System.out.println("The day after is " + dayAfter);


}

}

运行示例

【测试用例设计及分析】

三角形问题:测试用例

我们选择最常用的弱健壮测试,设计以下设计用例:
对于三角形问题,分别需要取的(边界)值:

Var Min Min- Min+ Nom Max- Max Max+
a 1 0 2 50 99 100 101
b 1 0 2 50 99 100 101
c 1 0 2 50 99 100 101

以下为弱健壮测试用例表:

对边a

测试用例编号 a b c 类型
0 1 50 50 Min
1 0 50 50 Min-
2 2 50 50 Min+
3 50 50 50 Nom
4 99 50 50 Max-
5 100 50 50 Max
6 101 50 50 Max+

对边b

测试用例编号 a b c 类型
7 50 1 50 Min
8 50 0 50 Min-
9 50 2 50 Min+
10 50 99 50 Max-
11 50 100 50 Max
12 50 101 50 Max+

对边c

测试用例编号 a b c 类型
7 50 50 1 Min
8 50 50 0 Min-
9 50 50 2 Min+
10 50 50 99 Max-
11 50 50 100 Max
12 50 50 101 Max+

以上是对变量a,对变量b, c测试用例相同,不再重复列举。根据公式,弱健壮测试用例数为: 6*n+1,19,和上表相同。

NextDate:测试用例

对于NextDate问题,分别需要取的(边界)值

Var Min Min- Min+ Nom Max- Max Max+
c1(Month,月) 1 0 2 6 11 12 13
c2(Day,日) 1 0 2 15 30 31 32
c3(YEAR,年) 1912 1911 1913 1981 2049 2050 2051

以下为弱健壮测试用例表:
对c1:

测试用例编号 c1 c2 c3 类型
0 1 15 1981 Min
1 0 15 1981 Min-
2 2 15 1981 Min+
3 6 15 1981 Nom
4 11 15 1981 Max-
5 12 15 1981 Max
6 13 15 1981 Max+

对c2:

测试用例编号 c1 c2 c3 类型
7 6 1 1981 Min
8 6 0 1981 Min-
9 6 2 1981 Min+
10 6 29 1981 Max-
11 6 30 1981 Max
12 6 31 1981 Max+

对c3

测试用例编号 c1 c2 c3 类型
13 6 15 1912 Min
14 6 15 1911 Min-
15 6 15 1913 Min+
16 6 15 2049 Max-
17 6 15 2050 Max
18 6 15 2051 Max+

根据公式,弱健壮测试用例数为: 6*n+1,该案例的测试用例数为19,符合上表。

【测试结果及分析】

在编写实验代码时,我使用的面向对象的编程方法,将输入、判断、输出都封装成了一个类TriangleProc。因此,编写测试类时,可以更加容易地实例化对象,调用对象中的方法进行测试。并且测试的方式、顺序、组合都会更灵活。

三角形问题:使用测试类进行测试

测试代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
package exps;

import procs.TriangleProc;

public class TriangleTesting_one {

public static void main(String[] args) {
TriangleProc triangleProc = new TriangleProc();

int[] sideAList = new int[]{1,0,2,50,99,100,101};
int[] sideBList = new int[]{50};
int[] sideCList = new int[]{50};


for (int sideA : sideAList) {
for (int sideB : sideBList) {
for (int sideC : sideCList) {
triangleProc.sideA = sideA;
triangleProc.sideB = sideB;
triangleProc.sideC = sideC;

triangleProc.verifyLengthRange(triangleProc.sideA);
triangleProc.verifyLengthRange(triangleProc.sideB);
triangleProc.verifyLengthRange(triangleProc.sideC);

triangleProc.verifyFormPrinciple(triangleProc);

System.out.println("三角形类型为:" + triangleProc.judgeTriangleType(triangleProc));
}
}
}


}

}

输出结果


满足预期

三角形问题:手动输入测试

测试用例0:

符合预期。

测试用例1:


符合预期。

测试用例2:

符合预期。

测试用例3:

符合预期。

测试用例4:

符合预期。

测试用例5:

符合预期。

测试用例6:

符合预期。

对于三角形测试,我们主要关注于两个验证函数:验证三角形两边之和大于第三边;验证三角形边的长度范围,以长度为变量,测试边界范围的值。

NextDate: 使用测试类进行测试

测试代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
package exps;

import procs.NextDate;

import java.util.Scanner;

public class NextDateTesting_one {

/**
* 驱动模块
* 函数:dateCheckFunction
* @param nextDate
*/
public void dateCheckFunction(NextDate nextDate, int year, int month, int day) {

if (year >= 1912 && year <= 2050) {
nextDate.year = year;
} else {
System.out.println("The YEAR is out of range");
}

if (month >= 1 && month <= 12) {
nextDate.month = month;
} else {
System.out.println("The MONTH is out of range");
}

if (day >= 1 && day <= 31) {
nextDate.day = day;
} else {
System.out.println("The DAY is out of range");
}

}


public static void main(String[] args) {

NextDate nextDate = new NextDate();
NextDateTesting_one nextDateTesting_one = new NextDateTesting_one();

int[] yearList = new int[]{1912, 1911, 1913, 2049, 2050, 2051};
int[] monthList = new int[]{1, 0, 2, 11, 12, 13};
int[] dayList = new int[]{1, 0, 2, 29, 30, 31};

int nomYear = 1981;
int nomMonth = 6;
int nomDay = 15;

/**
* 对year的弱健壮测试
*/
for (int year : yearList) {
// 检查输入的日期是否符合要求
nextDateTesting_one.dateCheckFunction(nextDate, year, nomMonth, nomDay);
// 根据nextDateFunction函数获取后一天的日期
String dayAfter = nextDate.nextDateFunction(nextDate.year,
nextDate.month, nextDate.day);

System.out.println("The day after is " + dayAfter);

}

/**
* 对month的弱健壮测试
*/
for (int month : monthList) {
// 检查输入的日期是否符合要求
nextDateTesting_one.dateCheckFunction(nextDate, nomYear, month, nomDay);
// 根据nextDateFunction函数获取后一天的日期
String dayAfter = nextDate.nextDateFunction(nextDate.year,
nextDate.month, nextDate.month);

System.out.println("The day after is " + dayAfter);

}

/**
* 对day的弱健壮测试
*/
for (int day : dayList) {
// 检查输入的日期是否符合要求
nextDateTesting_one.dateCheckFunction(nextDate, nomYear, nomMonth, day);
// 根据nextDateFunction函数获取后一天的日期
String dayAfter = nextDate.nextDateFunction(nextDate.year,
nextDate.month, nextDate.month);

System.out.println("The day after is " + dayAfter);

}

}
}

输入结果

在上述的测试代码中,分别对Year、Month和Day进行弱健壮测试,输出的结果和测试用例设计时的预期相符:

【实验总结】

在实际编程环境中,会遇到很多边界值,因此边界值测试可以很好地检查这些易出错的点上,系统的鲁棒性。
面向对象的编程,也会更好地帮助测试,会使得测试代码的编写更容易,实现高内聚,低耦合。