一、实验目的
掌握基于覆盖理论与基本路径的基本白盒测试方法和实践
二、实验要求
运用逻辑覆盖测试的覆盖准则设计被测程序的测试用例,并运行测试用例检查程序的正确与否,给出程序缺陷小结。
三、实验内容
根据各位同学自己的被测程序,分别作出各类白盒测试技术的用例设计和相应的Junit脚本。
所有的覆盖的技术:语句覆盖、判定覆盖、条件覆盖、判定/条件覆盖、组合覆盖、路径覆盖,基本路径测试方法。
包括的内容有:
1) 被测原代码
import java.util.Scanner; public class Commission { public static double commission(int headphone, int shell, int protector) { double back = 0; float sum = 0; sum = headphone * 80 + shell * 10 + protector * 8; if (sum < 1000) { back = sum * 0.1; // 小于1000时所抽取的佣金 } else if (sum >= 1000 && sum <= 1800) { back = 100 + (sum - 1000) * 0.15;// 计算1000--1800的佣金 } else if (sum >= 1800) { back = 220 + (sum - 1800) * 0.2;// 1800以上的佣金 } return back; } static int tu(String a) { int back; char a_c[] = a.toCharArray(); int len = a.length(); for (int i = 0; i <= len - 1; i++) // 逐个检查是否为数字,小数点同样不通过 { if (a_c[i] > '9' || a_c[i] < '0') { back = -1; return back; } } back = Integer.parseInt(a); return back; } public static void main(String[] args) { int pass = 0;// 设置初始判断循环是否通过的值 String headphone; String shell; String protector; @SuppressWarnings("resource") Scanner s = new Scanner(System.in); int headphone_i = 0; int shell_i = 0; int protector_i = 0; double back; while (pass == 0) { System.out.printf("请分别输入三种手机配件的销售情况:\n"); while (pass == 0) { System.out.printf("请输入耳机的销售数量:(输入exit退出)\n"); headphone = s.next(); if (headphone.equals("exit") == true) { System.exit(0); } else if (tu(headphone) == -1) { System.out.printf("输入的数据不合法,请重新输入!\n"); continue; } else { headphone_i = tu(headphone); break; } } while (pass == 0) { System.out.printf("请输入手机外壳的销售数量:\n"); shell = s.next(); if (tu(shell) == -1) { System.out.printf("输入的数据不合法,请重新输入!\n"); continue; } else { shell_i = tu(shell); break; } } while (pass == 0) { System.out.printf("请输入手机护膜的销售数量:\n"); protector = s.next(); if (tu(protector) == -1) { System.out.printf("输入的数据不合法,请重新输入!\n"); continue; } else { protector_i = tu(protector); break; } } back = commission(headphone_i, shell_i, protector_i); System.out.println("佣金为:" + back + "\n"); } } }
2)依据覆盖技术,测试用例列表:
commission函数DD-路径图:
语句覆盖、路径覆盖:
A-B-D-G
A-B-C-E-G
A-B-C-F-G
用例设计:
编号 | 输入 | 预期输出 | 实际输出 | 执行路径 | 是否通过 |
1 | 0 0 0 | 0 | 0 | ABDG | √ |
2 | 10 19 6 | 105.7 | 105.7 | ABCEG | √ |
3 | 32 10 1 | 393.6 | 393.6 | ABCFG | √ |
判定条件覆盖、组合覆盖:
编号 | B< 1000 | C >= 1000 | C <= 1800 | 路径 |
1 | T | F | T | BDG |
2 | F | T | T | BCEG |
3 | F | T | F | BCFG |
用例设计
编号 | 输入 | 预期输出 | 实际输出 | 执行路径 | 是否通过 | 覆盖条件 |
1 | 1 1 1 | 9.8 | 9.8 | ABDG | √ | 1 |
2 | 10 20 5 | 106 | 106 | ABCEG | √ | 2 |
3 | 20 40 0 | 260 | 260 | ABCFG | √ | 3 |
3)相应Junit测试脚本、执行结果
import static org.junit.Assert.*; import org.junit.After; import org.junit.Before; import org.junit.Test; public class CommissionTest { Commission com = new Commission(); @Before public void setUp() throws Exception { } @After public void tearDown() throws Exception { } @Test public void testCommission() { assertEquals(9.8,Commission.commission(1, 1, 1),0.00001); assertEquals(105.7, com.commission(10, 19, 6),0.00001); assertEquals(393.6, com.commission(32, 10, 1),0.00001); assertEquals(0,Commission.commission(0, 0, 0),0.00001); assertEquals(106, com.commission(10, 20, 5),0.00001); assertEquals(260, com.commission(20, 40, 0),0.00001); } }
结果:
4)给出测试参数化和打包测试的脚本,并生成执行结果
测试参数化脚本:
import static org.junit.Assert.assertEquals; import java.util.Arrays; import java.util.Collection; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.Parameterized; import org.junit.runners.Parameterized.Parameters; @RunWith(Parameterized.class) public class ParameterizedTest{ Commission com; private int headphone; private int shell; private int protector; private double result; @Parameters public static Collection data(){ return Arrays.asList( new Object[][]{ {0, 0, 0, 0}, {10, 19, 6, 105.7}, {32, 10, 1, 393.6}, {1, 1, 1, 9.8}, {10, 20, 5, 106}, {20, 40, 0, 260}, } ); } public ParameterizedTest(int headphone,int shell,int protector,double result){ com=new Commission(); this.headphone=headphone; this.shell=shell; this.protector=protector; this.result=result; } @Test public void testCommission() { assertEquals(result,com.commission(headphone, shell, protector), 0.00001); } }
执行结果:
注:图片中的类名与代码中的类名不一致的原因是因为为了打包测试,重新创建类一个junit测试类,图片中的运行结果是在第一次的基础上改的。
打包测试脚本:
import org.junit.runner.RunWith; import org.junit.runners.Suite; @RunWith(Suite.class) @Suite.SuiteClasses({CommissionTest.class, ParameterizedTest.class}) public class AllCommissionTest { }
执行结果:
4、测试小结:
- 测试找到的缺陷清单
无
- 对源代码的修改建议
实验1第三个程序要求commission函数返回的类型是float型。
- 测试总结与心得体会
Junit4提供的参数化测试及打包测试极大的方便了我们进行单元测试,然而我认为难点还在于测试用例的设计,本次实验我只针对commission函数,也就是最后的佣金计算函数进行了各种覆盖测试,而合法性输入判断函数并没有衔接在一起,如果我向commission函数输入了负数,而我期望的结果是它报错,但实际上单元测试的结果会出现结算佣金为负数,而不是报错,这时候我们需要将整个程序画在同一个流程图内吗?但是将整个程序画在同一流程图内,最后设计测试用例又未免显得太复杂。
另外本次实验测试的代码判断的条件其实有四个但在我看来实际上只有两个,事实上sum < 1000与sum >= 1000是一对相反的条件,而sum <= 1800与(sum >= 1800也是一对相反的条件,这使得我设计条件覆盖满足条件的时候很迷茫,不知道该怎么设计。