实 验 目 的:
(1)掌握软件测试的过程和方法。
(2)掌握测试用例的设计方法。
(3)熟悉测试计划说明书、测试记录与分析报告的编写。
实 验 环 境:
PC一台 、Junit、WORLD编辑工具
实 验 内 容 及 过 程:
实验要求:
1.根据所选的课程设计题目进行以下实验
2.用程序设计所规定的编程语言,编写一段代码实现软件需求给出的一个功能(每位同学所选的功能模块不同)。
3.制定测试计划、设计测试用例,特别是一些异常情况的处理。
4.模块的动态测试以黑盒法为主,辅以白盒法。重要执行路径的测试使用白盒法。白盒法必须先列出所有判定,再选择覆盖标准,根据不同的覆盖标准所列出的情况,设计测试用例。
5.阅读相关的软件开发标准文档,正确编写测试计划、测试记录与分析报告。
实验步骤:
1.编写一段代码实现软件项目的一个功能。
2.制定测试计划,设计软件项目相应的测试用例。
3.测试数据,调试运行策略。
4.编写测试记录与分析报告。
5.完成实验报告。

一、问题描述

用Java实现求两整数的加、减、乘、除运算结果,要求两整数的范围都是[0,100]。从键盘输入数m,数n,若不在[0,100]范围内,则输出提示语,要求重新输入,并且在做除法运算时,当除数为0时,输出提示语,说明除数不能为0。
将两数的范围定在[0,100],以更好的进行边界值分析,等价类测试等黑盒测试方法;为充分体现白盒测试的特点,有些地方故意用了if-else语句,while循环;另外,加、减、乘、除运算分别用了四个函数来计算,这样既可以在主函数中调用,又可以在Junit框架中分别对这四种运算进行测试。

二、程序源代码

package JunitTest;
import java.util.Scanner;
public class Computer {
    private  int a;
    private  int b;

    public  Computer (int x, int y)  //构造函数, 初始化
    {
            a=x;
            b=y;//注意:Junit中需要输入测试值在0-100范围内
    }

   public int limit() {
       if (a >= 0 && a <= 100) {
           if (b >= 0 && b <= 100) {
               return b;
           } else {
               System.out.println("输入n值不在要求区间,请重新输入n ");
           }
           return a;
       } else {
           System.out.println("输入m值不在要求区间,请重新输入m ");
       }
       return 0;
   }


    public int add ()
    {
          limit();
        return a+b;
    }

    public int minus ()
    {
        limit();
        return a-b;
    }

    public int multiply()
    {
        limit();
        return a*b;
    }

    public int divide ()
    {
        if(b!=0) {
            limit();
            return a / b;
        }
        else{
            System.out.println("除数不能为0! ");
        }
        return 0;
    }

    public static void main(String[] args)
    {
        Scanner scanner;
        scanner = new Scanner (System.in) ;
        System.out. println ("请输入0~100的两个m, n整数:");
        System.out.println("请输入第一个数:");
        do {//若输入值不在要求范围内,则有循环直到输入正确为止
            int m = scanner.nextInt();
            if (m >= 0 && m <= 100) {
                System.out.println("请输入第二个数:");
                while (true) {
                    int n = scanner.nextInt();
                    if (n >= 0 && n <= 100) {
                        Computer cpt = new Computer(m, n);
                        System.out.println("运算结果是:");
                        System.out.println("加法:" + m + "/" + n + "=" + cpt.add());
                        System.out.println("减法:" + m + "-" + n + "=" + cpt.minus());
                        System.out.println("乘法:" + m + "*" + n + "=" + cpt.multiply());
                        System.out.println("除法:" + m + "/" + n + "=" + cpt.divide());
                    } else
                        System.out.print("输入n值不在要求区间,请重新输入n:\n");
                }
            } else
                System.out.print("输入m值不在要求区间,请重新输入m:\n");
        } while (true);
    }

}

三、黑盒测试

1.边界值分析
输入要求是0-100之间的整数,因此产生0和100两个边界。可构造(50,0)、(50,1)、(50,50)、(50,99)、(50,100)、(0,50)、(1,50)、(99,50)、(100,50)、(50,-1)、(50,101)、(-1,50)、(101,50)这13组测试用例。

在这里插入图片描述

2.等价类划分
规定了输入值m,n的范围[0,100],则
变量的有效等价类:
M1={m:0≤m≤100}
N1={n:0≤n≤100}
变量的无效等价类:
M2={m:m≤0}
M3={m:m≥100}
N2={n:n≤0}
N3={n:n≥0}

在这里插入图片描述

3.因果图
1:输入m值在[0,100]以内 2:输入n值在[0,100]以内
12:输出结果 13:输入m值不在区间 14:输入n值不在区间

在这里插入图片描述

4.决策表法
变量的有效等价类:
M1={m:0≤m≤100}
N1={n:0≤n≤100}
变量的无效等价类:
M2={m:m≤0}
M3={m:m≥100}
N2={n:n≤0}
N3={n:n≥0}

在这里插入图片描述

四、白盒测试

程序的大致流程图如下:
在这里插入图片描述

1.语句覆盖
每个可执行的语句必须至少执行一次,则测试用例:

在这里插入图片描述

2.判定覆盖
每个判定必须至少获得一次“真”值和“假”值,则测试用例:
在这里插入图片描述

3.条件组合覆盖
每个判定中的每个条件的所有可能值(真/假)至少出现一次并且每个判定本身的结果(真/假)也至少出现一次,则测试用例:

在这里插入图片描述

4.路径覆盖
测试用例要求覆盖所有可能的路径,则测试用例:

在这里插入图片描述

五、测试代码

package JunitTest; 

import junit.framework.Test;
import junit.framework.TestCase;
import junit.framework.TestSuite;

public class ComputerTest extends TestCase {

    private Computer a;//定义变量
    private Computer b;
    private Computer c;
    private Computer d;

    public ComputerTest(String name) {
        super(name);//构造函数,使用super关键字直接引用父类TestCase的构造函数
    }

    protected void setUp() throws Exception {
        super.setUp();//建立环境,可以进行一些测试数据的初始化,还可以把数据库联接写在此处,以减少重复性工作,提高效率
        a = new Computer(12, 2);
        b = new Computer(101, 5);
        c = new Computer(5, 101);
        d = new Computer(1, 0);
    }

   public void tearDown() throws Exception {
        super.tearDown();
    }

    public void testAdd() {
        assertEquals(14, a.add());
    }

    public void testMinus() {
        assertEquals(10, a.minus());
    }

    public void testMultiply() {
        assertEquals(24, a.multiply());
    }

    public void testDivide() {
        assertEquals(6, a.divide());
    }

    public void testDivideByZero() {
        try {
            assertEquals(0, d.divide());//因divide()函数中当d=0时,返回0,所以这里测试应该成功,虽然希望得到“除数不能为0!”的情况
            fail("should have thrown an exception");//上面不抛出异常,不执行fail()
        }catch (Exception e){
            assertTrue(true);
        }
    }

    public void testAdd1() {
        try {
            assertEquals(106, b.add());//因divide()函数中当d=0时,返回0,所以这里测试应该成功,虽然希望得到“除数不能为0!”的情况
            fail("should have thrown an exception");//上面不抛出异常,不执行fail()
        }catch (Exception e){
            assertTrue(true);
        }
    }

    public void testAdd2() {
        try {
            assertEquals(106, c.add());//因divide()函数中当d=0时,返回0,所以这里测试应该成功,虽然希望得到“除数不能为0!”的情况
            fail("should have thrown an exception");//上面不抛出异常,不执行fail()
        }catch (Exception e){
            assertTrue(true);
        }
    }
}
    public static Test suite  ()
    {
        TestSuite suite=new TestSuite();
        suite.addTest(new ComputerTest("testAdd1"));
        suite.addTest(new ComputerTest("testDivideByZero"));
        return suite;
    }

运行结果截图:
在这里插入图片描述

(1)测试testDivideByZero,由于d=new Computer(1,0);除数不能为0,抛出异常;
(2)测试testAdd1()时,由于b=new Computer(101,5);assertEquals(106,b.add());输入值范围超过定义范围,抛出异常;
(3)测试testAdd2()时,由于c=new Computer(5,101);assertEquals(106,c.add());输入值范围超过定义范围,抛出异常。

扩展:
若在另一个ComputerTest1类中,要测试ComputerTest中的所有测试方法,则可以:

package JunitTest;

import junit.framework.Test;
import junit.framework.TestCase;
import junit.framework.TestSuite;

    public class ComputerTest1 extends TestCase
    {
    public ComputerTest1 (String name)
    {
        super(name);
    }

    public static Test suite ()
    {
        TestSuite suite=new TestSuite();
        suite.addTestSuite (ComputerTest.class);
        return suite;
    }
}

六.心得体会

在这次软件测试过程中,我扮演了用户、程序员、测试员三钟角色,为了充分体现黑盒、白盒以及Junit动态测试的特点,我特意设计了一个[0,100]之间的整数简单加减乘除运算。
对于黑盒测试,在设计测试用例时完全没有考虑程序内部的逻辑结构和内部特性,只纯粹的依据功能和要求来设计测试用例进行测试。测试时使用了多种测试方法,包括边界值测试,等价类测试,基于决策表的测试等。虽然黑盒测试很容易生成测试用例,但实际上只有一小部分可能的输入被测试到,某些代码得不到测试,不能直接对隐蔽了许多问题的特定程序段进行测试,不易进行充分性测试。
对于白盒测试,在设计测试用例时首先对程序进行分析,从程序的内部结构出发设计测试用例,涉及到程序的控制方法、源语句、编码细节、数据库设计等。设计测试用例时应用了白盒测试中的多种测试方法,其中包括:语句覆盖、判定覆盖、条件组合覆盖、路径覆盖等方法。
对于Junit,编写了另一段代码来测试要执行的代码,代码中的一个测试类(TestCase)包含了很多测试方法(testxxxx),每个测试方法中又有很多测试断言(assertXXXX),在方法中测试预期值是否和实际值一致。
总之,在这次测试设计让我对软件测试有了一个深入了解,对于测试方法、测试过程,都有了较好的认识,学会了如何进行黑盒测试、白盒测试、以及一些测试工具(如Junit)。当然,对于以后企业上的软件测试,还有待很大的提高。

Logo

开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!

更多推荐