JUnit 4 单元测试 Individual Project
——JUnit 4 单元测试
学习到JUnit单元测试,我拿来测试之前写过的一个计算器(两个依存类:Calc.java CalcFunction.java)。代码已放到github中。
贴出部分代码:
1 public class Calc extends javax.swing.JFrame{ 2 3 public Calc() { 4 initComponents(); 5 } 6 7 private void initComponents() { 8 java.awt.GridBagConstraints gridBagConstraints; 9 10 setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE); 11 setTitle("u8ba1u7b97u5668"); 12 setBounds(new java.awt.Rectangle(500, 50, 0, 0)); 13 setResizable(false); 14 15 ···//界面布局 16 17 } 18 //主要监听 19 ActionListener listenerEquals = new ActionListener() { 20 public void actionPerformed(ActionEvent e) { 21 formulaStand.setText(edit + "="); 22 hasPoint = false; 23 String result; 24 try { 25 result = CalcFunction.Evaluate(edit+"="); 26 } catch (Exception e1) { 27 result = "syntax error"; 28 } 29 if (Double.parseDouble(result)%1 == 0) { 30 editStand.setText(String.valueOf((int)Double.parseDouble((result)))); 31 }else{ 32 editStand.setText(String.valueOf((float)Double.parseDouble((result)))); 33 } 34 edit = "0"; 35 } 36 }; 37 }
GUI布局类,运行的结果如下图:通过Botton输入表达式,传入CalcFunction类计算结果
这是计算器实现功能计算的类:
1 package com.school.indivodial; 2 3 import java.util.EmptyStackException; 4 import java.util.Stack; 5 6 public class CalcFunction { 7 private static String[] TrnsInToSufix(String IFX) { // PFX放后缀表达式,IFX为中缀表达式 8 String PFX[] = new String[IFX.length()]; 9 StringBuffer numBuffer = new StringBuffer();// 用来保存一个数的 10 Stack<String> s = new Stack<String>();// 放操作符 11 String a; 12 s.push("=");// 第一个为等号 13 int i = 0, j = 0; 14 char ch; 15 16 ··· // 栈操作,中缀表达式转后缀表达式 17 18 return PFX; 19 } 20 21 public static String Evaluate(String IFX) throws Exception {// 后缀表达式求值 22 23 String PFX[] = null; 24 try { 25 PFX = TrnsInToSufix(IFX); 26 } catch (EmptyStackException e) { 27 return "syntax error"; 28 } 29 int i = 0; 30 double x1, x2, n; 31 String str; 32 Stack<String> s = new Stack<String>(); 33 while (PFX[i] != "=") { 34 str = PFX[i]; 35 switch (str.charAt(0)) { 36 case '0': 37 case '1': 38 case '2': 39 case '3': 40 case '4': 41 case '5': 42 case '6': 43 case '7': 44 case '8': 45 case '9': 46 s.push(str); 47 break; 48 case '+': 49 x1 = Double.parseDouble(s.pop()); 50 x2 = Double.parseDouble(s.pop()); 51 n = x1 + x2; 52 s.push(String.valueOf(n)); 53 break; 54 case '-': 55 x1 = Double.parseDouble(s.pop()); 56 x2 = Double.parseDouble(s.pop()); 57 n = x2 - x1; 58 s.push(String.valueOf(n)); 59 break; 60 case '×': 61 x1 = Double.parseDouble(s.pop()); 62 x2 = Double.parseDouble(s.pop()); 63 n = x1 * x2; 64 s.push(String.valueOf(n)); 65 break; 66 case '÷': 67 x1 = Double.parseDouble(s.pop()); 68 x2 = Double.parseDouble(s.pop()); 69 n = x2 / x1; 70 s.push(String.valueOf(n)); 71 break; 72 case 'o': 73 x1 = Double.parseDouble(s.pop()); 74 n = Math.log10(x1); 75 s.push(String.valueOf(n)); 76 break; 77 case 'n': 78 x1 = Double.parseDouble(s.pop()); 79 n = Math.log1p(x1); 80 s.push(String.valueOf(n)); 81 break; 82 case 'u221a'://'√' 83 x1 = Double.parseDouble(s.pop()); 84 n = Math.sqrt(x1); 85 s.push(String.valueOf(n)); 86 break;// 开方 87 case '^': 88 x1 = Double.parseDouble(s.pop()); 89 x2 = Double.parseDouble(s.pop()); 90 n = Math.pow(x2, x1); 91 s.push(String.valueOf(n)); 92 break; 93 ···//其他运算 94 95 } 96 i++; 97 } 98 String result = s.pop(); 99 return result; 100 } 101 102 }
下面进行单元测试:测试CalcFunction类的方法计算结果是否有错误。
首先要在该工程下导入JUnit库 具体做法:Build Path -> Config Build Path ... -> Add Libraries ... 选中JUnit Next-> 选择JUnit 4 Finished
添加完成
创建测试用例
new -> Java Test Case Name:CalcFunctionTest Next-> 选择要测试的方法 ->finished
自动生成一个测试类CalcFunctionTest,里面包含一些空的测试用例,@Test 注解的。只需要将这些测试用例稍作修改即可使用。完整的CalcFunctionTest代码如下:
1 package com.school.indivodial; 2 3 import static org.junit.Assert.assertEquals; 4 5 import org.junit.Test; 6 7 /** 8 * 9 * @author lendoon 10 *CalcFunction类是Calc类的功能类, 11 *Calc的UI输入中缀表达式调用CalcFunction的静态Evaluate方法计算返回结果 12 */ 13 public class CalcFunctionTest { 14 15 @Test 16 public void testEvaluate_basic() throws Exception { 17 Double expectedAnswer = Double.valueOf("90"); 18 Double actualAnswer = Double.valueOf(CalcFunction.Evaluate("100-(22+6×3)÷4=")); 19 assertEquals(expectedAnswer, actualAnswer); 20 } 21 22 @Test 23 public void testEvaluate_pow() throws Exception{ 24 Double expectedAnswer = Double.valueOf("1024"); 25 Double actualAnswer = Double.valueOf(CalcFunction.Evaluate("2^10=")); 26 assertEquals(expectedAnswer, actualAnswer); 27 } 28 29 @Test 30 public void testEvaluate_sqrt() throws Exception{ 31 Double expectedAnswer = Double.valueOf("8"); 32 Double actualAnswer = Double.valueOf(CalcFunction.Evaluate("√64=")); 33 assertEquals(expectedAnswer, actualAnswer); 34 } 35 36 @Test 37 public void testEvaluate_cos() throws Exception{ 38 Double expectedAnswer = Double.valueOf("1"); 39 Double actualAnswer = Double.valueOf(CalcFunction.Evaluate("COS(0)=")); 40 assertEquals(expectedAnswer, actualAnswer); 41 } 42 }
Run As -> JUnit Test,结果如图:
测试显示绿色的对号是通过的,显示蓝色叉号的,表示没通过failure。如图中的testEvaluate_cos测试方法。
运行失败,进度条会变成红褐色的,失败有两种情况:
处理结果与预期的有偏差(failure) 和 处理结果时,则直接抛出了异常——测试错误(error)
如图:测试失败的两种情况
Failure 一般由单元测试使用的断言方法判断失败引起,它表示在测试点发现了问题,如断言"1" 和"1+1=";
而 error 则是由代码异常引起,这是测试目的之外的发现,它可能产生于测试代码本身的错误(测试代码也是代码,同样无法保证完全没有缺陷),也可能是被测试代码中的一个隐藏的 bug 如图中测试代码传入"1+1"没有=,不是一个表达式,在程序运行中会报错。
全部测试成功时,进度条是绿色的:
通过测试,现在的代码已经比较稳定,可以作为 API 的一部分提供给其它模块使用了。
总结:
经过对JUnit 的了解,简单对之前写的计算器代码做个测试,收获颇丰:JUnit作为最佳实践测试任何可能的错误。单元测试不是用来证明您是对的,而是为了证明您没有错。JUnit还有更强大的功能等着我们去探索。