佘凤
摘 要:本文主要针对一个实际问题—自动售货机程序,进行分析、设计测试用例,并使用JUnit单元测试工具实现测试。
关键词:自动售货机程序;单元测试;JUnit
中图分类号:TP273 文献标识码:A
1 引言(Introduction)
自动售货机处理单价为5角钱的饮料。程序流程图如图1所示。功能如下:
(1)若投入5角钱或1元钱的硬币,按下“橙汁”或“啤酒”按钮,则送出相应饮料。
(2)若售货机没有零钱,则显示“零钱找完”的红灯亮,此时再投入一元硬币并按下按钮后,不送出饮料并且退出1元硬币。
(3)若有零钱找,则显示“零钱找完”的红灯灭,送出饮料并退还5角硬币。
图1 程序流程图
Fig.1 Program flow chart
2 问题分析(Problem analysis)
自动售货机业务中共有五个条件和五个结果,如表1所示。
表1 自动售货机原因和结果
Tab.1 Automatic vending machine cause and result
编号 原因 编号 结果
C1 售货机有零钱找 E1 零钱找完:当售货机中没有零钱的时候就有亮红灯
C2 投入1元硬币 E2 退还1元硬币:投入1元且售货机中没有零钱可找的时候
C3 投入5角硬币 E3 退还5角硬币:投入1元且售货机中有零钱可找的时候
C4 按下橙汁按钮 E4 送出橙汁饮料
C5 按下啤酒按钮 E5 送出啤酒饮料
使用因果图法,它能够生成没有重复性的且发现错误能力强的测试用例,而且对输入、输出同时进行了分析,考虑输入的组合以及输出对输入的依赖关系。画出因果图,如图2所示。
图2 因果图
Fig.2 Cause and effect diagram
中间状态是导出结果的进一步原因。中间状态如表2所示。
表2 中间状态
Tab.2 Intermediate state
编号 中间状态 操作
11 应该找5角钱零钱状态 投入1元硬币且按下饮料按钮
12 选商品状态 按下“橙汁”或“啤酒”按钮
13 能够找5角钱零钱状态 应找5角零钱并且售货机有零钱找
14 钱已付清 钱已付清
3 自动售货机程序测试(The vending machine
program test)
JUnit用于开发人员进行单元测试,适合一边编程,一边测试,可尽早纠正编程错误,减小纠正代价。根据因果图分析程序,有14种测试情况,设计测试数据,使用JUnit工具进行自动售货机程序测试。
说明:售货机程序初始化时:Beer:10;OrangeJuice:10;5 Cents:10;1 Dollar:10说明:5C代表5角钱,1D代表1元钱,Beer代表啤酒,OrangeJuice代表橙汁。
(1)各资源均有剩余,用户投币5角,选择啤酒。
public void testOperation1() {
String expectedResult = "Input Information\n" +"Type:Beer;Money:5 Cents;Change:0\n\n" +"Current State\n" +"Beer:9\n" +"OrangeJuice:10\n" +"5 Cents:11\n" +"1 Dollar:10";
assertEquals(expectedResult, obj.operation("Beer", "5C"));
}
(2)各资源均有剩余,用户投币5角,选择橙汁。
public void testOperation2() {
String expectedResult = "Input Information\n"+"Type:OrangeJuice;Money:5 Cents;Change:0\n\n" +"Current State\n"+"Beer:10\n"+"OrangeJuice:9\n" +"5 Cents:11\n" +"1 Dollar:10";
assertEquals(expectedResult, obj.operation("OrangeJuice", "5C"));
}
(3)各资源均有剩余,用户投币1元,选择啤酒。
public void testOperation3() {
String expectedResult = "Input Information\n"+ "Type:Beer;Money:1 Dollar;Change:5 Cents\n\n" +"Current State\n"+"Beer:9\n"+"OrangeJuice:10\n" +"5 Cents:9\n" +"1 Dollar:11";
assertEquals(expectedResult, obj.operation("Beer", "1D"));
}
(4)各资源均有剩余,用户投币1元,选择橙汁。
public void testOperation4() {
String expectedResult = "Input Information\n"+"Type:OrangeJuice;Money:1 Dollar;Change:5 Cents\n\n" +"Current State\n" +"Beer:10\n" +"OrangeJuice:9\n" +"5 Cents:9\n" +"1 Dollar:11";
assertEquals(expectedResult, obj.operation("OrangeJuice", "1D"));
}
(5)没有零钱,用户投币1元,选择啤酒。
public void testOperation5(){
SaleMachine obj=new SaleMachine(0,10,10,10);
String expectedResult ="Failure Information\n"+"Change Shortage";
assertEquals(expectedResult, obj.operation("Beer", "1D"));
}
(6)没有零钱,用户投币1元,选择橙汁。
public void testOperation6(){
SaleMachine obj=new SaleMachine(0,10,10,10);
String expectedResult="Failure Information\n"+"Change Shortage";
assertEquals(expectedResult, obj.operation("OrangeJuice", "1D"));
}
(7)没有啤酒,用户投币5角,选择啤酒。
public void testOperation8(){
SaleMachine obj=new SaleMachine(10,10,0,10);
String expectedResult="Failure Information\n"+"Beer Shortage";
assertEquals(expectedResult, obj.operation("Beer", "5C"));
}
(8)没有啤酒,用户投币1元,选择啤酒。
public void testOperation7(){
SaleMachine obj=new SaleMachine(10,10,0,10);
String expectedResult="Failure Information\n"+"Beer Shortage";
assertEquals(expectedResult, obj.operation("Beer", "1D"));
}
(9)没有橙汁,用户投币5角,选择橙汁。
public void testOperation9(){
SaleMachine obj=new SaleMachine(10,10,10,0);
String expectedResult="Failure Information\n"+"OrangeJuice Shortage";
assertEquals(expectedResult, obj.operation("OrangeJuice", "5C"));
}
(10)没有橙汁,用户投币1元,选择橙汁。
public void testOperation10(){
SaleMachine obj=new SaleMachine(10,10,10,0);
String expectedResult="Failure Information\n"+"OrangeJuice Shortage";
assertEquals(expectedResult, obj.operation("OrangeJuice", "1D"));
}
(11)各资源均有剩余,用户投币错误,选择啤酒。
public void testOperation11(){
String expectedResult="Failure Information\n"+"Money Error";
assertEquals(expectedResult, obj.operation("Beer", "1C"));
}
(12)各资源均有剩余,用户投币错误,选择橙汁。
public void testOperation12(){
String expectedResult="Failure Information\n"+"Money Error";
assertEquals(expectedResult, obj.operation("OrangeJuice", "1C"));
}
虽然在实际情况中不会有除啤酒和橙汁以外的选择,但是为了测试单元模块的所有输入输出情况,需要编写检测饮料类型的测试用例。
(13)各资源均有剩余,用户投币5角,选择可口可乐。
public void testOperation13(){
String expectedResult="Failure Information\n"+"Type Error";
assertEquals(expectedResult, obj.operation("Coca-cola", "5C"));
}
(14)各资源均有剩余,用户投币1元,选择可口可乐。
public void testOperation14(){
String expectedResult="Failure Information\n"+"Type Error";
assertEquals(expectedResult, obj.operation("Coca-cola", "1D"));
}
运行测试,查看测试结果。绿色表示测试通过,只要有一个测试未通过,会显示红色并列出未通过测试的方法。测试结果如图3所示。
图3 测试结果图
Fig.3 Test result chart
4 结论(Conclusion)
单元测试是验证代码行为是否满足预期的有效手段之一。不可否认,做测试是件很枯燥无趣的事情,而一遍又一遍的测试是让人生畏的工作。单元测试工具JUnit使这一切变得简单艺术起来。JUnit是Java中知名度最高的单元测试工具。JUnit设计非常小巧,但能却非常强大。本文主要针对一个实际问题,编写基于JUnit的单元测试用例;并在JUnit环境下设计并执行测试用例。实现自动售货机程序的测试。
参考文献(References)
[1] 于艳华,王素华.软件测试项目实战[M].北京:电子工业出版
社,2013.
[2] 武剑洁,陈传波,肖来元.软件测试技术基础[M].武汉:华中科
技大学出版社,2014.
[3] 吕云翔,王洋,肖咚.软件测试案例教程[M].北京:机械工业出
版社,2015.
作者简介:
佘 凤(1976-),女,硕士,软件设计师,讲师.研究领域:
软件测试.