黑盒测试——nextDate函数测试(等价类划分法、边界值分析法、判定表驱动法)

2020-12-07 00:00:00 测试 等价 判定

实验目的

(1)掌握应用黑盒测试技术进行测试用例设计。
(2)掌握对测试用例进行优化设计方法。

实验内容

日期问题
测试以下程序:该程序有三个输入变量month、day、year(month、day和year均为整数值,并且满足:1≤month≤12、1≤day≤31和1900≤year≤2050),分别作为输入日期的月份、日、年份,通过程序可以输出该输入日期在日历上隔一天的日期。例如,输入为2004 年11月30日,则该程序的输出为2004年12月1日。
(1)划分等价类
(2)按照等价类划分法设计测试用例;
(3)按照边界值分析法设计测试用例;
(4)按照判定表驱动法设计测试用例。
(5)编写nextDate函数;
(6)掌握Junit4的用法,使用Junit4测试nextDate函数。
JUnit4是JUnit框架有史以来的最大改进,其主要目标便是利用Java5的Annotation特性简化测试用例的编写。
掌握Junit4定义的一些常见Annotations:

org.junit.Test 
org.junit.Before
org.junit.After
org.junit.BeforeClass
org.junit.AfterClass
org.junit.Ignore
org.junit.runner.RunWith
org.junit.runners.Suite.SuiteClasses
org.junit.runners.Parameterized.Parameters

实验要求

(1)根据题目要求编写测试用例;
(2)准备nextDate函数,使用Junit4测试执行测试;
(3)实验结果要求给出测试用例集测试效果比较。
(4)撰写实验报告。

实验过程

(1)根据题目要求编写测试用例

划分等价类并编号

输入数据有效等价类无效等价类
(1) 1900到2050内的闰年整数(10) year<1900
(2) 1900到2050内的平年整数(11) year>2050
(12) 其他输入
(3) 1,3,5,7,8,10,12内的整数(13) month<1
(4) 4,6,9,11内的整数(14) 12<month
(5) 2(15) 其他输入
(6) 1~28(16) day<1
(7) 29(17) year为闰年 month=2时,29<day
(8) 30(18) year为非闰年 month=2时,28<day
(9) 31(19) month=1,3,5,7,8,10,12时,31<day
(20) month=4,6,9,11时,30<day
(21) day>31
(22) 其他输入

按照等价类划分法设计测试用例

1)为有效等价类设计测试用例

序号测试数据期望结果覆盖范围
12016 2 29下一天是2016年3月1日!(1)(5)(7)
22017 1 28下一天是2017年1月29日!(2)(3)(6)
32017 1 31下一天是2017年2月1日!(2)(3)(9)
42017 4 30下一天是2017年5月1日!(2)(4)(8)
52017 12 31下一天是2018年1月1日!(2)(3)(9)

2)为每一个无效等价类至少设计一个测试用例

序号输入数据期望结果覆盖范围
61899 3 1年的值不在指定范围之内(10)
72051 3 1年的值不在指定范围之内(11)
8205% 3 1无效的输入日期!(12)
91901 -1 1月的值不在指定范围之内(13)
101901 13 1月的值不在指定范围之内(14)
111901 1% 1无效的输入日期!(15)
121901 1 -1日的值不在指定范围之内(16)
132016 2 30日的值不在指定范围之内(17)
142017 2 29日的值不在指定范围之内(18)
152017 3 32日的值不在指定范围之内(19)
162017 4 31日的值不在指定范围之内(20)
172017 4 32日的值不在指定范围之内(21)
182017 4 3%无效的输入日期!(22)

按照边界值分析法设计测试用例

测试用例monthdayYear针对的有效类期望输出
17101889(1)(2)年的值不在指定范围内
27101900(1)(2)19000711
37101901(1)(2)19010711
47102049(1)(2)20490711
57102050(1)(2)20500711
67102051(1)(2)年的值不在指定范围内
70102019(3)~(6)月的值不在指定范围内
81102019(3)~(6)20190111
92102019(3)~(6)20190211
1011102019(3)~(6)20191111
1112102019(3)~(6)20191211
1213102019(3)~(6)月的值不在指定范围内
132272019(5)(7)~(9)20190228
142282019(5)(7)~(9)20190301
152292019(5)(7)~(9)日的值不在指定范围内
162282020(5)(7)~(9)20200229
172292020(5)(7)~(9)20200301
182302020(5)(7)~(9)日的值不在指定范围内
191302019(3)(9)(10)20190131
201312019(3)(9)(10)20190201
211322019(3)(9)(10)日的值不在指定范围内
224302019(4)(9)(10)20190501
234312019(4)(9)(10)日的值不在指定范围内
244322019(4)(9)(10)日的值不在指定范围内

按照判定表驱动法设计测试用例

条件桩

M 1 = m o n t h : 这 个 月 有 30 天 M_1={month:这个月有30天} M1=month:30
M 2 = m o n t h : 这 个 月 有 31 天 , 除 了 12 月 M_2={month:这个月有31天,除了12月} M2=month:3112
M 3 = m o n t h : 这 个 月 是 12 月 M_3={month:这个月是12月} M3=month:12
M 4 = m o n t h : 这 个 月 是 2 月 M_4={month:这个月是2月} M4=month:2
D 1 = d a y : 1 ≤ d a y ≤ 27 D_1={day:1≤day≤27} D1=day:1day27
D 2 = d a y : d a y = 28 D_2={day:day=28} D2=day:day=28
D 3 = d a y : d a y = 29 D_3={day:day=29} D3=day:day=29
D 4 = d a y : d a y = 30 D_4={day:day=30} D4=day:day=30
D 5 = d a y : d a y = 31 D_5={day:day=31} D5=day:day=31
Y 1 = y e a r : y e a r 是 闰 年 Y_1={year:year是闰年} Y1=year:year
Y 2 = y e a r : y e a r 不 是 闰 年 Y_2={year:year不是闰年} Y2=year:year

动作桩

A 0 : 不 可 能 A_0:不可能 A0
A 1 : d a y + 1 A_1:day+1 A1:day+1
A 2 : d a y 复 位 A_2:day复位 A2:day
A 3 : m o n t h + 1 A_3:month+1 A3:month+1
A 4 : m o n t h 复 位 A_4:month复位 A4:month
A 5 : y e a r + 1 A_5:year+1 A5:year+1

判断表

规则12345678910111213141516171819202122
条件:
C 1 : m o n t h 是 C_1:month是 C1:month M 1 M_1 M1 M 1 M_1 M1 M 1 M_1 M1 M 1 M_1 M1 M 1 M_1 M1 M 2 M_2 M2 M 2 M_2 M2 M 2 M_2 M2 M 2 M_2 M2 M 2 M_2 M2 M 3 M_3 M3 M 3 M_3 M3 M 3 M_3 M3 M 3 M_3 M3 M 3 M_3 M3 M 4 M_4 M4 M 4 M_4 M4 M 4 M_4 M4 M 4 M_4 M4 M 4 M_4 M4 M 4 M_4 M4 M 4 M_4 M4
C 2 : d a y 是 C_2:day是 C2:day D 1 D_1 D1 D 2 D_2 D2 D 3 D_3 D3 D 4 D_4 D4 D 5 D_5 D5 D 1 D_1 D1 D 2 D_2 D2 D 3 D_3 D3 D 4 D_4 D4 D 5 D_5 D5 D 1 D_1 D1 D 2 D_2 D2 D 3 D_3 D3 D 4 D_4 D4 D 5 D_5 D5 D 1 D_1 D1 D 2 D_2 D2 D 2 D_2 D2 D 3 D_3 D3 D 3 D_3 D3 D 4 D_4 D4 D 5 D_5 D5
C 3 : y e a r 是 C_3:year是 C3:year − – − – − – − – − – − – − – − – − – − – − – − – − – − – − – − – Y 1 Y_1 Y1 Y 2 Y_2 Y2 Y 1 Y_1 Y1 Y 2 Y_2 Y2 − – − –
动作:
A 0 = 不 可 能 A_0=不可能 A0= √ \surd √ \surd √ \surd √ \surd
A 1 : d a y + 1 A_1:day+1 A1:day+1 √ \surd √ \surd √ \surd √ \surd √ \surd √ \surd √ \surd √ \surd √ \surd √ \surd √ \surd √ \surd √ \surd
A 2 : d a y 复 位 A_2:day复位 A2:day √ \surd √ \surd √ \surd √ \surd √ \surd
A 3 : m o n t h + 1 A_3:month+1 A3:month+1 √ \surd √ \surd √ \surd √ \surd
A 4 : m o n t h 复 位 A_4:month复位 A4:month √ \surd
A 5 : y e a r + 1 A_5:year+1 A5:year+1 √ \surd

简化判断表

规则1
2
3
456
7
8
9
1011
12
13
14
15161718192021
22
条件:
C 1 : m o n t h 是 C_1:month是 C1:month M 1 M_1 M1 M 1 M_1 M1 M 1 M_1 M1 M 2 M_2 M2 M 2 M_2 M2 M 3 M_3 M3 M 3 M_3 M3 M 4 M_4 M4 M 4 M_4 M4 M 4 M_4 M4 M 4 M_4 M4 M 4 M_4 M4 M 4 M_4 M4
C 2 : d a y 是 C_2:day是 C2:day D 1 D_1 D1
D 2 D_2 D2
D 3 D_3 D3
D 4 D_4 D4 D 5 D_5 D5 D 1 D_1 D1
D 2 D_2 D2
D 3 D_3 D3
D 4 D_4 D4
D 5 D_5 D5 D 1 D_1 D1
D 2 D_2 D2
D 3 D_3 D3
D 4 D_4 D4
D 5 D_5 D5 D 1 D_1 D1 D 2 D_2 D2 D 2 D_2 D2 D 3 D_3 D3 D 4 D_4 D4 D 4 D_4 D4
D 5 D_5 D5
C 3 : y e a r 是 C_3:year是 C3:year − – − – − – − – − – − – − – − – Y 1 Y_1 Y1 Y 2 Y_2 Y2 Y 1 Y_1 Y1 Y 2 Y_2 Y2 − –
动作:
A 0 = 不 可 能 A_0=不可能 A0= √ \surd √ \surd √ \surd
A 1 : d a y + 1 A_1:day+1 A1:day+1 √ \surd √ \surd √ \surd √ \surd √ \surd
A 2 : d a y 复 位 A_2:day复位 A2:day √ \surd √ \surd √ \surd √ \surd √ \surd
A 3 : m o n t h + 1 A_3:month+1 A3:month+1 √ \surd √ \surd √ \surd √ \surd
A 4 : m o n t h 复 位 A_4:month复位 A4:month √ \surd
A 5 : y e a r + 1 A_5:year+1 A5:year+1 √ \surd

设计测试用例

测试用例monthdayyear期望输出
1~3916201920190917
4930201920191001
59312019日的值不在指定范围内
6~9116201920190117
10131201920190201
11~141216201920191217
151231201920200101
16216201920190217
17228201920190301
18228202020200229
19229202020200301
202292019日的值不在指定范围内
21,222302019日的值不在指定范围内

(2)编写nextDate函数,使用Junit4测试执行测试

被测代码

package io.shentuzhigang.demo.blackbox;

import java.util.regex.Pattern;

/** * @author ShenTuZhiGang * @version 1.0.0 * @date 2021-05-06 15:43 */
public class Date { 
    private static final Pattern pattern = Pattern.compile("^[-\\+]?[\\d]*$");

    public static String nextDate(String s_year, String s_month, String s_day) { 
        //检测是否存在无效字符
        if (!(isInteger(s_year) && isInteger(s_month) && isInteger(s_day))) { 
            return "无效的输入日期!";
        }
        //将字符串转为int
        int year = Integer.parseInt(s_year);
        int month = Integer.parseInt(s_month);
        int day = Integer.parseInt((s_day));
        boolean flag = false;
        if (year < 1900 || year > 2050) { 
            return ("年的值不在指定范围之内");
        } else if (month > 12 || month < 1) { 
            return ("月的值不在指定范围之内");
        } else if (day > 31 || day < 1) { 
            return ("日的值不在指定范围之内");
        }

        switch (month) { 
            case 1:
            case 3:
            case 5:
            case 7:
            case 8:
            case 10:
                if (day == 31) { 
                    day = 1;
                    month = month + 1;
                } else { 
                    day = day + 1;
                }
                break;
            case 4:
            case 6:
            case 9:
            case 11:
                if (day == 30) { 
                    day = 1;
                    month = month + 1;
                } else if (day == 31) { 
                    flag = true;
                } else { 
                    day = day + 1;
                }
                break;
            case 12:
                if (day == 31) { 
                    day = 1;
                    month = 1;
                    year = year + 1;
                } else { 
                    day = day + 1;
                }
                break;
            case 2: { 
                if (((year % 4 == 0 && year % 100 != 0) || year % 400 == 0)) { 
                    // 闰年
                    if (day == 29) { 
                        day = 1;
                        month = 3;
                    } else if (day < 29) { 
                        day = day + 1;
                    } else { 
                        flag = true;
                        // day超过29
                    }
                } else { 
                    //非闰年
                    if (day == 28) { 
                        day = 1;
                        month = 3;
                    } else if (day < 28) { 
                        day = day + 1;
                    } else { 
                        flag = true;
                    }
                }

            }
            break;
            default:
        }

        if (year > 2050) { 
            return ("年的值不在指定范围之内");
        } else if (flag) { 
            return ("日的值不在指定范围之内");
        } else { 
            return ("下一天是" + year + "年" + month + "月" + day + "日!");
        }
    }

    /** * 判断输入字符串是否是整数型 * * @param str * @return */
    public static boolean isInteger(String str) { 
        return pattern.matcher(str).matches();
    }
}

package io.shentuzhigang.demo.test.blackbox;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;


public class Exp2 { 


    public static void main(String[] args) throws IOException { 
        // TODO Auto-generated method stub
        int year, month, day;
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        System.out.println("输入年:");
        year = Integer.parseInt(br.readLine());
        System.out.println("输入月:");
        month = Integer.parseInt(br.readLine());
        System.out.println("输入日:");
        day = Integer.parseInt(br.readLine());
        String nextday = Exp2.nextDate(year, month, day);
        System.out.println("下一天为" + nextday);
    }

    public static String nextDate(int y, int m, int d) { 
        int year, month, day;
        year = y;
        month = m;
        day = d;
        String result = new String();

        switch (month) { 
            case 1:
            case 3:
            case 5:
            case 7:
            case 8:
            case 10:
                if (day == 31) { 
                    day = 1;
                    month = month + 1;
                } else
                    day = day + 1;
                break;
            case 4:
            case 6:
            case 9:
            case 11:
                if (day == 30) { 
                    day = 1;
                    month = month + 1;
                } else if (day == 31) { 
                    System.out.println("无效输入日期!");
                    //continue;
                } else
                    day = day + 1;
                break;
            case 12:
                if (day == 31) { 
                    day = 1;
                    month = 1;
                    year = year + 1;
                } else if (day < 31) { 
                    day = day + 1;
                }
                break;
            case 2: { 
                if (day == 28)
                    if (((year % 4 == 0 && year % 100 != 0) || year % 400 == 0)) { 
                        day = 29;
                    } else { 
                        day = 1;
                        month = 3;
                    }
                else if (day == 29) { 
                    day = 1;
                    month = 3;
                } else if (day < 28) { 
                    day = day + 1;
                } else { 
                    //System.out.println("无效输入日期!");
                    result = "无效输入日期!";
                    //continue;
                }
            }
            break;
            default:
        }

        if (year >= 1900 && year <= 2050 && month <= 12 && month >= 1
                && day <= 31 && day >= 1) { 
            //System.out.println("下一天是" + year + "年" + month + "月" + day + "日!");
            StringBuilder months = new StringBuilder();
            StringBuilder days = new StringBuilder();
            if (month < 10)
                months = months.append(0).append(month);
            else
                months = months.append(month);
            if (day < 10)
                days = days.append(0).append(day);
            else
                days = days.append(day);
            StringBuilder resultB = new StringBuilder().append(year).append(months).append(days);
            result = resultB.toString();
        } else if (year < 1900 || year > 2050) { 
            //System.out.println("年的值不在指定范围内");
            result = "年的值不在指定范围内";
        } else if (month > 12 || month < 1) { 
            //System.out.println("月的值不在指定范围内");
            result = "月的值不在指定范围内";
        } else if (day > 31 || day < 1) { 
            //System.out.println("日的值不在指定范围内");
            result = "日的值不在指定范围内";
        } else result = null;
        return result;
    }
}


测试过程

等价类划分法

测试类
package io.shentuzhigang.demo.blackbox;

import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import org.junit.runners.Parameterized.Parameters;

import java.util.Arrays;
import java.util.Collection;

/** * @author ShenTuZhiGang * @version 1.0.0 * @date 2021-05-06 15:43 */
@RunWith(Parameterized.class)
public class DateTests { 
    private String input1;
    private String input2;
    private String input3;
    private String expected;

    @Parameters
    public static Collection<?> prepareData(){ 
        String [][] object = { 
                // 有效等价类
                { "2016","2","29","下一天是2016年3月1日!"},
                { "2017","1","28","下一天是2017年1月29日!"},
                { "2017","1","31","下一天是2017年2月1日!"},
                { "2017","4","30","下一天是2017年5月1日!"},
                // 无效等价类
                { "1899","3","1","年的值不在指定范围之内"},
                { "2051","3","1","年的值不在指定范围之内"},
                { "205%","3","1","无效的输入日期!"},
                { "1901","-1","1","月的值不在指定范围之内"},
                { "1901","13","1","月的值不在指定范围之内"},
                { "1901","1%","1","无效的输入日期!"},
                { "1901","1","-1","日的值不在指定范围之内"},
                { "2016","2","30","日的值不在指定范围之内"},
                { "2017","2","29","日的值不在指定范围之内"},
                { "2017","3","32","日的值不在指定范围之内"},
                { "2017","4","31","日的值不在指定范围之内"},
                { "2017","4","32","日的值不在指定范围之内"},
                { "2017","4","3%","无效的输入日期!"}
        };
        return Arrays.asList(object);
    }
    public DateTests(String input1,String input2,String input3,String expected){ 
        this.input1 = input1;
        this.input2 = input2;
        this.input3 = input3;
        this.expected = expected;

    }
    @Test
    public void testDate(){ 
        String result = Date.nextDate(input1,input2,input3);
        Assert.assertEquals(expected,result);
    }
}


测试结果

《黑盒测试——nextDate函数测试(等价类划分法、边界值分析法、判定表驱动法)》

边界值分析法

测试类
package io.shentuzhigang.demo.test.blackbox;

import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;

import java.util.Arrays;
import java.util.Collection;

/** * @author ShenTuZhiGang * @version 1.0.0 * @date 2021-05-13 14:55 */
@RunWith(Parameterized.class)
public class DateBoundaryTests { 
    private int input1;
    private int input2;
    private int input3;
    private String expected;

    @Parameterized.Parameters
    public static Collection<?> prepareData(){ 
        Object [][] object = { 
                //年
                { 1889, 7, 10, "年的值不在指定范围内"},
                { 1900, 7, 10, "19000711"},
                { 1901, 7, 10, "19010711"},
                { 2049, 7, 10, "20490711"},
                { 2050, 7, 10, "20500711"},
                { 2051, 7, 10, "年的值不在指定范围内"},
                //月
                { 2019, 0, 10, "月的值不在指定范围内"},
                { 2019, 1, 10, "20190111"},
                { 2019, 2, 10, "20190211"},
                { 2019, 11, 10, "20191111"},
                { 2019, 12, 10, "20191211"},
                { 2019, 13, 10, "月的值不在指定范围内"},
                //日
                { 2019, 2, 27, "20190228"},
                { 2019, 2, 28, "20190301"},
                { 2019, 2, 29, "日的值不在指定范围内"},
                { 2020, 2, 28, "20200229"},
                { 2020, 2, 29, "20200301"},
                { 2020, 2, 30, "日的值不在指定范围内"},

                { 2019, 1, 30, "20190131"},
                { 2019, 1, 31, "20190201"},
                { 2019, 1, 32, "日的值不在指定范围内"},
                { 2019, 4, 30, "20190501"},
                { 2019, 4, 31, "日的值不在指定范围内"},
                { 2019, 4, 32, "日的值不在指定范围内"},
                
        };
        return Arrays.asList(object);
    }
    public DateBoundaryTests(int input1,int input2,int input3,String expected){ 
        this.input1 = input1;
        this.input2 = input2;
        this.input3 = input3;
        this.expected = expected;

    }
    @Test
    public void testDate(){ 
        String result = Exp2.nextDate(input1,input2,input3);
        Assert.assertEquals(expected, result);
    }
}

测试结果

《黑盒测试——nextDate函数测试(等价类划分法、边界值分析法、判定表驱动法)》

判定表驱动法

测试类
package io.shentuzhigang.demo.test.blackbox;

import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;

import java.util.Arrays;
import java.util.Collection;

/** * @author ShenTuZhiGang * @version 1.0.0 * @date 2021-05-13 14:59 */
@RunWith(Parameterized.class)
public class DateDecisionTests { 
    private int input1;
    private int input2;
    private int input3;
    private String expected;

    @Parameterized.Parameters
    public static Collection<?> prepareData(){ 
        Object [][] object = { 
                { 2019, 9, 16, "20190917"},
                { 2019, 9, 30, "20191001"},
                { 2019, 9, 31, "日的值不在指定范围内"},
                { 2019, 1, 16, "20190117"},
                { 2019, 1, 31, "20190201"},
                { 2019, 12, 16, "20191217"},
                { 2019, 12, 31, "20200101"},
                { 2019, 2, 16, "20190217"},   //7
                { 2019, 2, 28, "20190301"},    //8
                { 2020, 2, 28, "20200229"},
                { 2020, 2, 29, "20200301"},
                { 2019, 2, 29, "日的值不在指定范围内"},   //11
                { 2019, 2, 30, "日的值不在指定范围内"},
        };
        return Arrays.asList(object);
    }
    public DateDecisionTests(int input1,int input2,int input3,String expected){ 
        this.input1 = input1;
        this.input2 = input2;
        this.input3 = input3;
        this.expected = expected;

    }
    @Test
    public void testDate(){ 
        String result = Exp2.nextDate(input1,input2,input3);
        Assert.assertEquals(expected, result);
    }
}

测试结果

《黑盒测试——nextDate函数测试(等价类划分法、边界值分析法、判定表驱动法)》

缺陷分析

  1. 用例?发生故障的原因是程序先判断day为29就变为3月1日,而不先判断是否为闰年,于是用例?的输出结果为2007-3-1而不是无效输入日期。
  2. 用例?发生故障的原因是程序没有先判断接收的三个参数是否在指定范围内,而是先根据month进行数据处理,再判断处理后的参数是否在指定范围内,用例?的参数因为month为3所以直接day+1由0变成1再判断day在指定范围内,所以用例?的输出结果为1998-3-1而不是日的值不在指定范围内。

心得与体会

(1)掌握应用黑盒测试技术进行测试用例设计。
(2)掌握对测试用例进行优化设计方法。
(3)能用Junit实施参数化测试

参考文章

使用等价类划分法以及Junit的参数化测试,测试nextDate函数
使用边界值分析法与判定表驱动法设计测试用例,测试nextDate函数

    原文作者:Starzkg
    原文地址: https://blog.csdn.net/weixin_43272781/article/details/116454710
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。

相关文章