你的位置:首页 > Java教程

[Java教程]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("\u8ba1\u7b97\u5668");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 }

Calc.java

 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.java

 

  下面进行单元测试:测试CalcFunction类的方法计算结果是否有错误。

首先要在该工程下导入JUnit 具体做法:Build Path -> Config Build Path ... -> Add Libraries ... 选中JUnit Next-> 选择JUnit 4 Finished 

添加完成

创建测试用例  

 new -> Java Test Case  Name:CalcFunctionTest Next-> 选择要测试的方法 ->finished

 1 package com.school.indivodial; 2  3 import static org.junit.Assert.assertEquals; 4  5 import org.junit.Test; 6  7 /** 8  *  9  * @author lendoon10  *CalcFunction类是Calc类的功能类,11  *Calc的UI输入中缀表达式调用CalcFunction的静态Evaluate方法计算返回结果12 */13 public class CalcFunctionTest {14   15   @Test16   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   @Test23   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   @Test30   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   @Test37   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 }

CalcFunctionTest.java

 

自动生成一个测试类CalcFunctionTest,里面包含一些空的测试用例,@Test 注解的。只需要将这些测试用例稍作修改即可使用。完整的CalcFunctionTest代码如下:

Run As -> JUnit Test,结果如图:

 

 测试显示绿色的对号是通过的,显示蓝色叉号的,表示没通过failure。如图中的testEvaluate_cos测试方法。

 

运行失败,进度条会变成红褐色的,失败有两种情况:

处理结果与预期的有偏差(failure) 和  处理结果时,则直接抛出了异常——测试错误(error)

如图:测试失败的两种情况 

Failure 一般由单元测试使用的断言方法判断失败引起,它表示在测试点发现了问题,如断言"1" 和"1+1=";

而 error 则是由代码异常引起,这是测试目的之外的发现,它可能产生于测试代码本身的错误(测试代码也是代码,同样无法保证完全没有缺陷),也可能是被测试代码中的一个隐藏的 bug 如图中测试代码传入"1+1"没有=,不是一个表达式,在程序运行中会报错。

 

 全部测试成功时,进度条是绿色的:

 通过测试,现在的代码已经比较稳定,可以作为 API 的一部分提供给其它模块使用了。

 

 总结:

  经过对JUnit 的了解,简单对之前写的计算器代码做个测试,收获颇丰:JUnit作为最佳实践测试任何可能的错误。单元测试不是用来证明您是对的,而是为了证明您没有错。JUnit还有更强大的功能等着我们去探索。

   

JUnit是一个开放源代码的Java测试框架,用于编写和运行可重复的测试。他是用于单元测试框架体系xUnit的一个实例(用于java语言)。它包括以下特性:
1、用于测试期望结果的断言(Assertion)
2、用于共享共同测试数据的测试工具
3、用于方便的组织和运行测试的测试套件
4、图形和文本的测试运行器    (源于百度百科。相对于百科,wiki百科要简洁得多)