【软件测试】黑盒测试技术——等价类划分和边界值分析

  • Post author:
  • Post category:其他


黑盒测试技术也称功能测试、数据驱动的测试、基于规格说明的测试。
测试方法有:等价类划分法、边界值分析法、决策表法、因果图法、错误推测法、正交试验法和场景法。
本文先介绍等价类划分法和边界值分析法。

等价类划分法

1.概念:
根据需求对输入范围进行细分,然后在分出的每一个区域内选取一个有代表性的测试数据开展测试。
等价类=有效等价类+无效等价类
2.方法步骤:
依据常用方法划分等价类;
为每一个等价类规定一个唯一编号用作标识符;
设计一个新用例,使它能够尽可能多地覆盖尚未覆盖的有效等价类,重复上面的步骤,直到所有有效等价类都被用例覆盖;
设计一个新用例,要求仅覆盖一个尚未被覆盖的无效等价类,重复上面的步骤,直到所有无效等价类都被用例覆盖。
3.深入探讨:
单缺陷和多缺陷假设产生弱等价类和强等价类测试之分
是否进行无效数据处理产生健壮和一般等价类测试之分
具体可以查阅相关资料!

边界值分析法

1.概念:
边界值分析法就是对输入或输出的边界值进行测试的一种黑盒测试方法,通常作为等价类划分法的补充;
基于“错误更可能出现在输入变量的极值附近”原理
2.方法步骤:
在最小值(min)、略高于最小值(min+)、正常值(nom)、略低于最大值(max-)、最大值(max)处取变量值;
根据输入变量个数设计测试用例。


两种测试用例生成方法对于揭露程序的错误有什么异同点


异:边界值分析是对输入的边界值进行测试,未来查找在边界值上发生的错误;等价类划分所有的输入可能都被考虑进去,不仅仅考虑到边界值的出错;大量的错误是发生在输入或输出范围的边界上,而不是发生在输入输出范围的内部。因此针对各种边界情况设计测试用例,可以查出更多的错误。

同:均可扑抓边界值这类较容易发生的错误。通常边界值分析法是作为对等价类划分法的补充,这种情况下,其测试用例来自等价类的边界。

实例分析

题目:对电话账单来说,春季和秋季的标准时间与夏时制时间的转换会带来有意思的问题。春季,这种转换发生在(3 月末,4 月初的)星期日凌晨 2:00 时,这时时钟要设置为凌晨 3: 00 时。对称的转换通常发生在 10 月最后一个星期日,时钟要从 2:59:59 调回到 2:00:00。

请为采用以下费率计算用户的每月通话费:

(1)通话时间<=20 分钟时,每分钟收费 0.05 美元,通话时间不到 1 分钟时按 1 分钟计算。

(2)通话时间>20 分钟时,收费 1.00 美元,外加每分钟 0.10 美元,超过 20 分钟的部分,不到 1 分钟时按 1 分钟计算。

假设:

(1)通话计费时间从被叫方应答开始计算,到呼叫方挂机时结束。

(2)通话时间的秒数四舍五入到分钟。×(按标准:不到 1 分钟时按 1 分钟计算)

(3)没有超过 20 个小时的通话。

程序:

Long_tel_server.java:

package Main_class;

import java.io.IOException;
import java.text.DateFormat;
import java.util.Calendar;
import java.util.Scanner;

import Tool_class.Calculate_free;
import Tool_class.Judge_date;

//账单类,长途通话服务
public class Long_tel_server {
    Calendar c1=java.util.Calendar.getInstance();
    Calendar c2=java.util.Calendar.getInstance();

    public void Input(){

        String s1="2017-03-14 09:25:10";
        String s2="2017-03-14 11:56:11";
        Calendar st=java.util.Calendar.getInstance();
        Calendar et=java.util.Calendar.getInstance();
        int sy,smonth,sd,sh,sm,ss;
        int ey,emonth,ed,eh,em,es;

        while(true){
        @SuppressWarnings("resource")
        Scanner s11=new Scanner(System.in);
        s1=s11.nextLine();
        @SuppressWarnings("resource")
        Scanner s22=new Scanner(System.in);
        s2=s22.nextLine();  
        DateFormat df=new java.text.SimpleDateFormat("yyyy-MM-dd,HH:mm:ss");
          String[] s1Arr=s1.split("[- , :]");
          sy=Integer.parseInt(s1Arr[0]);
          smonth=Integer.parseInt(s1Arr[1]);
          sd=Integer.parseInt(s1Arr[2]);
          sh=Integer.parseInt(s1Arr[3]);
          sm=Integer.parseInt(s1Arr[4]);
          ss=Integer.parseInt(s1Arr[5]);

          String[] s2Arr=s2.split("[- , :]");
          ey=Integer.parseInt(s2Arr[0]);
          emonth=Integer.parseInt(s2Arr[1]);
          ed=Integer.parseInt(s2Arr[2]);
          eh=Integer.parseInt(s2Arr[3]);
          em=Integer.parseInt(s2Arr[4]);
          es=Integer.parseInt(s2Arr[5]);
          System.err.println(s1);
          System.err.println(s2);
          if(sy<1900||sy>2200||ey<1900||ey>2200){
            System.out.print("输入年份错误,范围为1900<=years<=2200,请重输入年份");  
            }
             else if(smonth<1||smonth>12||emonth<1||emonth>12){
            System.out.print("输入月份错误,范围为1<=months<=12,请重输入月份");
            }
            /*else if(sd<1||sd>31||ed<1||ed>31){
            System.out.print("输入日错误,范围为1<=days<=31,请重输入日"); 
            }*/
            else if(sh<0||sh>=24||eh<0||eh>=24){
                System.out.print("输入小时错误,范围为0<=hours<=24,请重输入小时");

            }
            else if(sm<0||sm>60||em<0||em>60){
                System.out.print("输入分钟错误,范围为0<=minutes<=60,请重输入分钟");

            }
            else if(ss<0||ss>60||es<0||es>60){
                System.out.print("输入秒数错误,范围为0<=seconds<=60,请重输入秒数"); 
                }
            else {
                 try
                 {
                    st.setTime(df.parse(s1));
                    et.setTime(df.parse(s2));
                 }catch(java.text.ParseException e){
                System.err.println("日期格式输入不正确,程序终止!");
                System.exit(0);
                }
            break;
            }
        }//输入时间合法
        c1=st;
        c2=et;      
    }


    public static void main(String[] args) throws IOException {
        //接收用户输入并对其进行检查
        Long_tel_server ls=new Long_tel_server();
        ls.Input();

        if(ls.c1.compareTo(ls.c2)>0)
        {
            System.err.println("开始通话时间大于结束通话时间,输入有误,本次计费作废!");
            System.exit(0);
        }
        if(ls.c1.compareTo(ls.c2)==0)
        {
            System.err.println("开始通话时间等于结束通话时间,对方未接听,本次计费作废!");
            System.exit(0);
        }
        System.out.println(ls.c1);
        System.out.println(ls.c2);

        //输入时间合法,则进行计算
        Judge_date judge_date=new Judge_date(ls.c1,ls.c2);
        int rs=judge_date.judge();//将通话日期传入计算时长(考虑了时制、秒数,返回通话时长)
        //输出返回通话时长
        //System.out.println(rs);
        if(rs==0){
            System.err.println("通话时间超过20小时,输入有误,本次计费作废!");  
            System.exit(0);
        }
        int totalminiute=rs;//按照电话账单最终计算出来的通话时长

        Calculate_free cf=new Calculate_free();//计算一次通话的话费
        double cost=cf.calculate(totalminiute);

         System.out.println();
         System.out.println("本次通话的话费为:"+cost+"美元");

    }
}

Judge_date.java

package Tool_class;

import java.util.Calendar;

//判断日期并进行日期转换,没有超过20个小时的通话
public class Judge_date {
    private Calendar start_time;
    private Calendar finish_time;
    public Judge_date(Calendar s,Calendar f){
        start_time=s;
        finish_time=f;
    }
    //判断当天是否是周日
    public boolean Is_Sunday(Calendar date){
        int ss= date.get(Calendar.DAY_OF_WEEK); //秒
        if(ss==1) return true;
        return false;//Calendar中1-星期天,2-星期一,3-星期二,4-星期三,5-...
    }

    //得到当天是本周的第几天
    public int getWeekDay(int year, int month, int day)
    {
        int weekday;
        for(;month<=0||month>12;)
        {
            if(month<=0)
            {
                year-=1;
                month+=12;
            }
            else if(month>12)
            {
                year+=1;
                month-=12;
            }
        }
        weekday=year>0?(5+(year+1)+(year-1)/4-(year-1)/100+(year-1)/400)%7: (5+year+year/4-year/100+year/400)%7;
        weekday=month>2?(weekday+2*(month+1)+3*(month+1)/5)%7: (weekday+2*(month+2)+3*(month+2)/5)%7;
        if(((year%4==0&&year%100!=0)||year%400==0)&&month>2)
        {
            weekday=(weekday+1)%7;
        }
        weekday=(weekday+day)%7;
        return weekday;
        }


    //计算通话时长
    public int judge(){
        int sy,smonth,sd,sh,sm,ss;
        @SuppressWarnings("unused")
        int ey,emonth,ed,eh,em,es;
        float totalsecond;
        int totalminiute;

        sy=start_time.get(Calendar.YEAR);//年
        smonth=start_time.get(Calendar.MONTH) + 1;//月
        sd=start_time.get(Calendar.DATE);       //日
        sh=start_time.get(Calendar.HOUR_OF_DAY);
        sm=start_time.get(Calendar.MINUTE);
        ss=start_time.get(Calendar.SECOND);

        ey=finish_time.get(Calendar.YEAR);//年
        emonth=finish_time.get(Calendar.MONTH) + 1;//月
        ed=finish_time.get(Calendar.DATE);       //日
        eh=finish_time.get(Calendar.HOUR_OF_DAY);
        em=finish_time.get(Calendar.MINUTE);
        es=finish_time.get(Calendar.SECOND);
        /*
        *计算三月末四月初的周日
        *
        */
        int i;
        for(i = 0; i < 10; i++){
            if(getWeekDay(sy,3,26+i)==0){//是周日//开始年,3月,0/26,1/27,2/28,3/29,4/30,5/31,6/32/1,7/33/2,8/34/3,9/35/4
                    if(i == 0 || i == 1)continue;//周日 i=0、1   
                    else break;//周日,i=2,3,4,5,6,7,8,9
        }//i
        /*
        *计算十月最后一个周日
        *
        */
        }
        int j;
        for(j = 7; j > 0; j --){
            if(getWeekDay(sy,10,31-j)==0)//10月24,25,26,27,28,29,30日
            break;//周日,j=7,6,5,4,3,2,1
        }

        if(ed > sd)//计算两个日期实际相差时长
        totalsecond = 24*60*60-(sh*60*60+sm*60+ss)+eh*60*60+em*60+es;   
        else totalsecond = (eh*60*60+em*60+es)-(sh*60*60+sm*60+ss);

        float haha=totalsecond%60;//秒数取余,
        if(haha>0.0)
        totalminiute = (int) (totalsecond/60)+1;
        else totalminiute = (int) (totalsecond/60);

        //通话时长大于20小时
        int a=(int) (totalminiute/60);//计算通话时长,向下取整,一个有多少小时
        if(a>20){//通话时长大于20小时,返回0,因为计算出来的分钟不会出现0,“不满1分钟按1min计算”原则
            return 0;
        }

        //周日,i=2,3,4,5,6,7,8,9
        if(smonth == 3 && sd == 26 + i && sh < 2 && eh >= 3)
                totalminiute -= 60;//三月末、四月初的周日
        //周日,j=7,6,5,4,3,2,1
        if(smonth == 10 && sd == 31 - j && sh < 3)
                totalminiute += 60;//十月份的最后一个周日
            System.out.println(totalminiute);   //按照电话账单最终计算出来的通话时长 
            return totalminiute;
    }
}

Calculate_free.java

package Tool_class;
//日期判断类返回的日期进行计算,情况一,二,三(正常)
public class Calculate_free {
    //根据通话时长,计算话
    private double  cost;
    //返回话费
    public double calculate(int totalminiute){
        if(totalminiute <= 20)
         cost = 0.05 * totalminiute;
            else
             cost = 1 + (totalminiute-20)*0.1;
        double  cost_free=cost;
        return cost_free;

    }
}

程序中存在的问题:3月末4月初的周末并没有判断出来,导致处于该时间段的通话时间计算出错。



版权声明:本文为qq_32507527原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。