所谓单元测试是测试应用程序的功能是否能够按需要正常运行,并且确保是在开发人员的水平上,单元测试生成图片。单元测试是一个对单一实体(类或方法)的测试。单元测试是每个软件公司提高产品质量、满足客户需求的重要环节。
单元测试可以由两种方式完成:
手工测试 | 自动化测试 | |
---|---|---|
定义 | 手动执行测试用例并不借助任何工具的测试被称为人工测试。 | 借助工具支持并且利用自动工具执行用例被称为自动测试。 |
效率 | 消耗时间并单调:由于测试用例是由人力资源执行,所以非常缓慢并乏味。 | 快速自动化运行测试用例时明显比人力资源快。 |
人力资源要求 | 人力资源上投资巨大:由于测试用例需要人工执行,所以在人工测试上需要更多的试验员。 | 人力资源投资较少:测试用例由自动工具执行,所以在自动测试中需要较少的试验员。 |
可信度 | 可信度较低:人工测试可信度较低是可能由于人工错误导致测试运行时不够精确。 | 可信度更高:自动化测试每次运行时精确地执行相同的操作。 |
程式化 | 非程式化:编写复杂并可以获取隐藏的信息的测试的话,这样的程序无法编写。 | 程式化:试验员可以编写复杂的测试来显示隐藏信息。 |
JUnit 是一个 Java 编程语言的单元测试框架。JUnit 在测试驱动的开发方面有很重要的发展,是起源于 JUnit 的一个统称为 xUnit 的单元测试框架之一。
JUnit 促进了“先测试后编码”的理念,强调建立测试数据的一段代码,可以先测试,然后再应用。这个方法就好比“测试一点,编码一点,测试一点,编码一点……”,增加了程序员的产量和程序的稳定性,可以减少程序员的压力和花费在排错上的时间。
单元测试用例是一部分代码,可以确保另一端代码(方法)按预期工作。为了迅速达到预期的结果,就需要测试框架。JUnit 是 java 编程语言理想的单元测试框架。
一个正式的编写好的单元测试用例的特点是:已知输入和预期输出,即在测试执行前就已知。已知输入需要测试的先决条件,预期输出需要测试后置条件。
每一项需求至少需要两个单元测试用例:一个正检验,一个负检验。如果一个需求有子需求,每一个子需求必须至少有正检验和负检验两个测试用例。
本地环境设置
JUnit 是 Java 的一个框架,所以最根本的需要是在你的机器里装有 JDK。
JDK | 1.5或1.5以上 |
---|---|
内存 | 没有最小要求 |
磁盘空间 | 没有最小要求 |
操作系统 | 没有最小要求 |
上表的没有最小要求不是代表Junit不占空间,而是只要能运行起java程序,就能运行Junit(等价于Junit需要的要求和jdk需要的要求相同)。
现在打开控制台,执行以下 java 要求。
操作系统 | 任务 | 命令 |
---|---|---|
Windows | 打开命令操作台 | c:>java -version |
Linux | 打开命令终端 | $ java -version |
Mac | 打开终端 | machine:~ joseph$ java -version |
我们来验证一下所有操作系统的输出:
操作系统 | 输出 |
---|---|
Windows | java 版本 “1.6.0_21” Java(TM)SE 运行环境(build 1.6.0_21-b07) Java 热点(TM)客户端虚拟机(build 17.0-b17,混合模式,共享) |
Linux | java 版本“1.6.0_21” Java(TM)SE 运行环境(build 1.6.0_21-b07) Java 热点(TM)客户端虚拟机(build 17.0-b17,混合模式,共享) |
Mac | java 版本“1.6.0_21” Java(TM)SE 运行环境(build 1.6.0_21-b07) Java 热点(TM)64-字节服务器虚拟机(build 17.0-b17,混合模式,共享) |
如果你还没有安装 Java,从以下网址安装 http://www.oracle.com/technetwork/java/javase/downloads/index.html Java SDK。我们采用 Java 1.6.0_21 作为本教程的安装版本。
设置 JAVA_HOME 环境变量,使之指向基本目录位置,即在你机器上安装 Java 的位置。
OS | 输出 |
---|---|
Windows | 设置环境变量 JAVA_HOME to C:Program FilesJavajdk1.6.0_21 |
Linux | 输出 JAVA_HOME=/usr/local/java-current |
Mac | 输出 JAVA_HOME=/Library/Java/Home |
系统路径添加 Java 编译器位置。
OS | 输出 |
---|---|
Windows | 在系统变量路径末端添加字符串 ;C:Program FilesJavajdk1.6.0_21in |
Linux | 输出 PATH=$PATH:$JAVA_HOME/bin/ |
Mac | 不需要 |
使用以上解释的 Java-version 命令验证 Java 安装。
从 http://www.junit.org 下载 JUnit 最新版本的压缩文件。在编写这个教程的同时,我已经下载了 Junit-4.10.jar 并且将它复制到 C:>JUnit 文件夹里了。
OS | 档案名称 |
---|---|
Windows | junit4.10.jar |
Linux | junit4.10.jar |
Mac | junit4.10.jar |
设置 JUNIT_HOME 环境变量,使之指向基本目录位置,即在你机器上安装 JUNIT 压缩文件的位置。假设,我们已经在以下不同的操作系统的 JUNIT 文件夹里存储了 junit4.10.jar。
OS | 输出 |
---|---|
Windows | 设置环境变量 JUNIT_HOME 到 C:JUNIT |
Linux | 输出 JUNIT_HOME=/usr/local/JUNIT |
Mac | 输出 JUNIT_HOME=/Library/JUNIT |
设置 CLASSPATH 环境变量,使之指向 JUNIT 压缩文件位置。假设,我们已经在以下不同的操作系统的 JUNIT 文件夹里存储了 junit4.10.jar 。
OS | 输出 |
---|---|
Windows | 设置环境变量 CLASSPATH 到 %CLASSPATH%;%JUNIT_HOME%junit4.10.jar;.; |
Linux | 输出 CLASSPATH=$CLASSPATH:$JUNIT_HOME/junit4.10.jar:. |
Mac | 输出 CLASSPATH=$CLASSPATH:$JUNIT_HOME/junit4.10.jar:. |
在 C: > JUNIT_WORKSPACE 中创建一个 java 类文件,名称为 TestJunit。
import org.junit.Test;import static org.junit.Assert.assertEquals;public class TestJunit { @Test public void testAdd() { String str= "Junit is working fine"; assertEquals("Junit is working fine",str); }}
在 C: > JUNIT_WORKSPACE 中创建一个 java 类文件,名称为TestRunner,来执行测试用例。
import org.junit.runner.JUnitCore;import org.junit.runner.Result;import org.junit.runner.notification.Failure;public class TestRunner { public static void main(String[] args) { Result result = JUnitCore.runClasses(TestJunit.class); for (Failure failure : result.getFailures()) { System.out.println(failure.toString()); } System.out.println(result.wasSuccessful()); }}
利用 javac 编译器按照以下方式编写类。
C:JUNIT_WORKSPACE>javac TestJunit.java TestRunner.java
现在运行 Test Runner 来看结果。
C:JUNIT_WORKSPACE>java TestRunner
验证输出。
true
什么是 Junit 测试框架?
JUnit 是一个回归测试框架,被开发者用于实施对应用程序的单元测试,加快程序编制速度,同时提高编码的质量。JUnit 测试框架能够轻松完成以下任意两种结合:
JUnit 测试框架具有以下重要特性:
测试工具是一整套固定的工具用于基线测试。测试工具的目的是为了确保测试能够在共享且固定的环境中运行,因此保证测试结果的可重复性。它包括:
让我们来看一个例子:
import junit.framework.*;public class JavaTest extends TestCase { protected int value1, value2; // assigning the values protected void setUp(){ value1=3; value2=3; } // test method to add two values public void testAdd(){ double result= value1 + value2; assertTrue(result == 6); }}
测试套件意味捆绑几个测试案例并且同时运行。在 JUnit 中,@RunWith 和 @Suite 都被用作运行测试套件。以下为使用 TestJunit1 和 TestJunit2 的测试分类:
import org.junit.runner.RunWith;import org.junit.runners.Suite;//JUnit Suite Test@RunWith(Suite.class)@Suite.SuiteClasses({ TestJunit1.class ,TestJunit2.class})public class JunitTestSuite {}import org.junit.Test;import org.junit.Ignore;import static org.junit.Assert.assertEquals;public class TestJunit1 { String message = "Robert"; MessageUtil messageUtil = new MessageUtil(message); @Test public void testPrintMessage() { System.out.println("Inside testPrintMessage()"); assertEquals(message, messageUtil.printMessage()); }}import org.junit.Test;import org.junit.Ignore;import static org.junit.Assert.assertEquals;public class TestJunit2 { String message = "Robert"; MessageUtil messageUtil = new MessageUtil(message); @Test public void testSalutationMessage() { System.out.println("Inside testSalutationMessage()"); message = "Hi!" + "Robert"; assertEquals(message,messageUtil.salutationMessage()); }}
测试运行器 用于执行测试案例。以下为假定测试分类成立的情况下的例子:
import org.junit.runner.JUnitCore;import org.junit.runner.Result;import org.junit.runner.notification.Failure;public class TestRunner { public static void main(String[] args) { Result result = JUnitCore.runClasses(TestJunit.class); for (Failure failure : result.getFailures()) { System.out.println(failure.toString()); } System.out.println(result.wasSuccessful()); }}
测试分类是在编写和测试 JUnit 的重要分类。几种重要的分类如下:
现在我们将应用简单的例子来一步一步教你如何使用 Junit。
/** This class prints the given message on console.*/public class MessageUtil { private String message; //Constructor //@param message to be printed public MessageUtil(String message){ this.message = message; } // prints the message public String printMessage(){ System.out.println(message); return message; } }
在C: > JUNIT_WORKSPACE路径下创建一个文件名为 TestJunit.java 的类
import org.junit.Test;import static org.junit.Assert.assertEquals;public class TestJunit { String message = "Hello World"; MessageUtil messageUtil = new MessageUtil(message); @Test public void testPrintMessage() { assertEquals(message,messageUtil.printMessage()); }}
在 C: > JUNIT_WORKSPACE 路径下创建一个文件名为 TestRunner.java 的类来执行测试案例
import org.junit.runner.JUnitCore;import org.junit.runner.Result;import org.junit.runner.notification.Failure;public class TestRunner { public static void main(String[] args) { Result result = JUnitCore.runClasses(TestJunit.class); for (Failure failure : result.getFailures()) { System.out.println(failure.toString()); } System.out.println(result.wasSuccessful()); }}
用 javac 编译 MessageUtil、Test case 和 Test Runner 类。
C:JUNIT_WORKSPACE>javac MessageUtil.java TestJunit.java TestRunner.java
现在运行 Test Runner,它可以运行在所提供的 Test Case 类中定义的测试案例。
C:JUNIT_WORKSPACE>java TestRunner
检查运行结果
Hello Worldtrue
现在更新 C: > JUNIT_WORKSPACE 路径下的 TestJunit,并且检测失败。改变消息字符串。
import org.junit.Test;import static org.junit.Assert.assertEquals;public class TestJunit { String message = "Hello World"; MessageUtil messageUtil = new MessageUtil(message); @Test public void testPrintMessage() { message = "New Word"; assertEquals(message,messageUtil.printMessage()); }}
让我们保持其他类不变,再次尝试运行相同的 Test Runner
import org.junit.runner.JUnitCore;import org.junit.runner.Result;import org.junit.runner.notification.Failure;public class TestRunner { public static void main(String[] args) { Result result = JUnitCore.runClasses(TestJunit.class); for (Failure failure : result.getFailures()) { System.out.println(failure.toString()); } System.out.println(result.wasSuccessful()); }}
现在运行在 Test Case 类中提供的即将运行测试案例的 Test Runner
C:JUNIT_WORKSPACE>java TestRunner
检查运行结果
Hello WorldtestPrintMessage(TestJunit): expected:<[New Wor]d> but was:<[Hello Worl]d>false
JUnit 中的最重要的程序包是 junit.framework
它包含了所有的核心类。一些重要的类列示如下:
序号 | 类的名称 | 类的功能 |
---|---|---|
1 | Assert | assert 方法的集合 |
2 | TestCase | 一个定义了运行多重测试的固定装置 |
3 | TestResult | TestResult 集合了执行测试样例的所有结果 |
4 | TestSuite | TestSuite 是测试的集合 |
下面介绍的是 org.junit.Assert
类:
public class Assert extends java.lang.Object
这个类提供了一系列的编写测试的有用的声明方法。只有失败的声明方法才会被记录。Assert
类的重要方法列式如下:
序号 | 方法和描述 |
---|---|
1 | void assertEquals(boolean expected, boolean actual) 检查两个变量或者等式是否平衡 |
2 | void assertFalse(boolean condition) 检查条件是假的 |
3 | 检查对象不是空的 |
4 | 检查对象是空的 |
5 | 检查条件为真 |
6 | 在没有报告的情况下使测试不通过 |
下面让我们在例子中来测试一下上面提到的一些方法。在 C: > JUNIT_WORKSPACE 目录下创建一个名为 TestJunit1.java
的类。
import org.junit.Test;import static org.junit.Assert.*;public class TestJunit1 { @Test public void testAdd() { //test data int num= 5; String temp= null; String str= "Junit is working fine"; //check for equality assertEquals("Junit is working fine", str); //check for false condition assertFalse(num > 6); //check for not null value assertNotNull(str); }}
接下来,我们在 C: > JUNIT_WORKSPACE 目录下创建一个文件名为 TestRunner1.java
的类来执行测试案例。
import org.junit.runner.JUnitCore;import org.junit.runner.Result;import org.junit.runner.notification.Failure;public class TestRunner1 { public static void main(String[] args) { Result result = JUnitCore.runClasses(TestJunit1.class); for (Failure failure : result.getFailures()) { System.out.println(failure.toString()); } System.out.println(result.wasSuccessful()); }}
用 javac 编译 Test case
和 Test Runner
类
C:JUNIT_WORKSPACE>javac TestJunit1.java TestRunner1.java
现在运行 Test Runner
它将运行在 Test Case
类中定义并提供的测试样例。
C:JUNIT_WORKSPACE>java TestRunner1
检查输出结果。
true
下面介绍的是 org.junit.TestCaset
类:
public abstract class TestCase extends Assert implements Test
测试样例定义了运行多重测试的固定格式。TestCase
类的一些重要方法列式如下:
序号 | 方法和描述 |
---|---|
1 | int countTestCases() 为被run(TestResult result) 执行的测试案例计数 |
2 | TestResult createResult() 创建一个默认的 TestResult 对象 |
3 | String getName() 获取 TestCase 的名称 |
4 | TestResult run() 一个运行这个测试的方便的方法,收集由TestResult 对象产生的结果 |
5 | void run(TestResult result) 在 TestResult 中运行测试案例并收集结果 |
6 | void setName(String name) 设置 TestCase 的名称 |
7 | void setUp() 创建固定装置,例如,打开一个网络连接 |
8 | void tearDown() 拆除固定装置,例如,关闭一个网络连接 |
9 | String toString() 返回测试案例的一个字符串表示 |
我们在例子中尝试一下上文提到的方法。在 C: > JUNIT_WORKSPACE 路径下创建一个名为TestJunit2.java
的类。
import junit.framework.TestCase;import org.junit.Before;import org.junit.Test;public class TestJunit2 extends TestCase { protected double fValue1; protected double fValue2; @Before public void setUp() { fValue1= 2.0; fValue2= 3.0; } @Test public void testAdd() { //count the number of test cases System.out.println("No of Test Case = "+ this.countTestCases()); //test getName String name= this.getName(); System.out.println("Test Case Name = "+ name); //test setName this.setName("testNewAdd"); String newName= this.getName(); System.out.println("Updated Test Case Name = "+ newName); } //tearDown used to close the connection or clean up activities public void tearDown( ) { }}
接下来,在 C: > JUNIT_WORKSPACE 路径下创建一个名为 TestRunner2.java
的类来执行测试案例。
import org.junit.runner.JUnitCore;import org.junit.runner.Result;import org.junit.runner.notification.Failure;public class TestRunner2 { public static void main(String[] args) { Result result = JUnitCore.runClasses(TestJunit2.class); for (Failure failure : result.getFailures()) { System.out.println(failure.toString()); } System.out.println(result.wasSuccessful()); }}
用 javac 编译 Test case
和 Test Runner
类
C:JUNIT_WORKSPACE>javac TestJunit2.java TestRunner2.java
现在运行 Test Runner
它将运行在 Test Case
类中定义并提供的测试样例。
C:JUNIT_WORKSPACE>java TestRunner2
检查输出结果。
No of Test Case = 1Test Case Name = testAddUpdated Test Case Name = testNewAddtrue
下面定义的是 org.junit.TestResult
类:
public class TestResult extends Object
TestResult
类收集所有执行测试案例的结果。它是收集参数层面的一个实例。这个实验框架区分失败和错误。失败是可以预料的并且可以通过假设来检查。错误是不可预料的问题就像 ArrayIndexOutOfBoundsException
。TestResult
类的一些重要方法列式如下:
序号 | 方法和描述 |
---|---|
1 | 在错误列表中加入一个错误 |
2 | 在失败列表中加入一个失败 |
3 | 显示测试被编译的这个结果 |
4 | int errorCount() 获取被检测出错误的数量 |
5 | Enumeration errors() 返回错误的详细信息 |
6 | int failureCount() 获取被检测出的失败的数量 |
7 | void run(TestCase test ) 运行 TestCase |
8 | int runCount() 获得运行测试的数量 |
9 | void startTest(Test test) 声明一个测试即将开始 |
10 | void stop() 标明测试必须停止 |
在 C: > JUNIT_WORKSPACE 路径下创建一个名为 TestJunit3.java
的类。
import org.junit.Test;import junit.framework.AssertionFailedError;import junit.framework.TestResult;public class TestJunit3 extends TestResult { // add the error public synchronized void addError(Test test, Throwable t) { super.addError((junit.framework.Test) test, t); } // add the failure public synchronized void addFailure(Test test, AssertionFailedError t) { super.addFailure((junit.framework.Test) test, t); } @Test public void testAdd() { // add any test } // Marks that the test run should stop. public synchronized void stop() { //stop the test here }}
接下来,在 C: > JUNIT_WORKSPACE 路径下创建一个名为 TestRunner3.java
的类来执行测试案例。
import org.junit.runner.JUnitCore;import org.junit.runner.Result;import org.junit.runner.notification.Failure;public class TestRunner3 { public static void main(String[] args) { Result result = JUnitCore.runClasses(TestJunit3.class); for (Failure failure : result.getFailures()) { System.out.println(failure.toString()); } System.out.println(result.wasSuccessful()); }}
用 javac 编译 Test case
和 Test Runner
类
C:JUNIT_WORKSPACE>javac TestJunit3.java TestRunner3.java
现在运行 Test Runner
它将运行在 Test Case
类中定义并提供的测试样例。
C:JUNIT_WORKSPACE>java TestRunner3
检查输出结果。
true
下面定义的是 org.junit.TestSuite
类:
public class TestSuite extends Object implements Test
TestSuite
类是测试的组成部分。它运行了很多的测试案例。TestSuite
类的一些重要方法列式如下:
序号 | 方法和描述 |
---|---|
1 | void addTest(Test test) 在套中加入测试。 |
2 | void addTestSuite(Class<? extends TestCase> testClass) 将已经给定的类中的测试加到套中。 |
3 | int countTestCases() 对这个测试即将运行的测试案例进行计数。 |
4 | String getName() 返回套的名称。 |
5 | void run(TestResult result) 在 TestResult 中运行测试并收集结果。 |
6 | void setName(String name) 设置套的名称。 |
7 | Test testAt(int index) 在给定的目录中返回测试。 |
8 | int testCount() 返回套中测试的数量。 |
9 | static Test warning(String message) 返回会失败的测试并且记录警告信息。 |
在 C: > JUNIT_WORKSPACE 路径下创建一个名为 JunitTestSuite.java
的类。
import junit.framework.*;public class JunitTestSuite { public static void main(String[] a) { // add the test's in the suite TestSuite suite = new TestSuite(TestJunit1.class, TestJunit2.class, TestJunit3.class ); TestResult result = new TestResult(); suite.run(result); System.out.println("Number of test cases = " + result.runCount()); }}
用 javac 编译 Test suit
C:JUNIT_WORKSPACE>javac JunitTestSuite.java
现在运行 Test Suit
C:JUNIT_WORKSPACE>java JunitTestSuite
检查输出结果。
No of Test Case = 1Test Case Name = testAddUpdated Test Case Name = testNewAddNumber of test cases = 3
在这里你将会看到一个应用 POJO 类,Business logic 类和在 test runner 中运行的 test 类的 JUnit 测试的例子。
在 C: > JUNIT_WORKSPACE 路径下创建一个名为 EmployeeDetails.java 的 POJO 类。
public class EmployeeDetails { private String name; private double monthlySalary; private int age; /** * @return the name */ public String getName() { return name; } /** * @param name the name to set */ public void setName(String name) { this.name = name; } /** * @return the monthlySalary */ public double getMonthlySalary() { return monthlySalary; } /** * @param monthlySalary the monthlySalary to set */ public void setMonthlySalary(double monthlySalary) { this.monthlySalary = monthlySalary; } /** * @return the age */ public int getAge() { return age; } /** * @param age the age to set */ public void setAge(int age) { this.age = age; }}
EmployeeDetails 类被用于
在 C: > JUNIT_WORKSPACE 路径下创建一个名为 EmpBusinessLogic.java 的 business logic 类
public class EmpBusinessLogic { // Calculate the yearly salary of employee public double calculateYearlySalary(EmployeeDetails employeeDetails){ double yearlySalary=0; yearlySalary = employeeDetails.getMonthlySalary() * 12; return yearlySalary; } // Calculate the appraisal amount of employee public double calculateAppraisal(EmployeeDetails employeeDetails){ double appraisal=0; if(employeeDetails.getMonthlySalary() < 10000){ appraisal = 500; }else{ appraisal = 1000; } return appraisal; }}
EmpBusinessLogic 类被用来计算
在 C: > JUNIT_WORKSPACE 路径下创建一个名为 TestEmployeeDetails.java 的准备被测试的测试案例类
import org.junit.Test;import static org.junit.Assert.assertEquals;public class TestEmployeeDetails { EmpBusinessLogic empBusinessLogic =new EmpBusinessLogic(); EmployeeDetails employee = new EmployeeDetails(); //test to check appraisal @Test public void testCalculateAppriasal() { employee.setName("Rajeev"); employee.setAge(25); employee.setMonthlySalary(8000); double appraisal= empBusinessLogic.calculateAppraisal(employee); assertEquals(500, appraisal, 0.0); } // test to check yearly salary @Test public void testCalculateYearlySalary() { employee.setName("Rajeev"); employee.setAge(25); employee.setMonthlySalary(8000); double salary= empBusinessLogic.calculateYearlySalary(employee); assertEquals(96000, salary, 0.0); }}
TestEmployeeDetails 是用来测试 EmpBusinessLogic 类的方法的,它
现在让我们在 C: > JUNIT_WORKSPACE 路径下创建一个名为 TestRunner.java 的类来执行测试案例类
import org.junit.runner.JUnitCore;import org.junit.runner.Result;import org.junit.runner.notification.Failure;public class TestRunner { public static void main(String[] args) { Result result = JUnitCore.runClasses(TestEmployeeDetails.class); for (Failure failure : result.getFailures()) { System.out.println(failure.toString()); } System.out.println(result.wasSuccessful()); }}
用javac编译 Test case 和 Test Runner 类
C:JUNIT_WORKSPACE>javac EmployeeDetails.java EmpBusinessLogic.java TestEmployeeDetails.java TestRunner.java
现在运行将会运行 Test Case 类中定义和提供的测试案例的 Test Runner
C:JUNIT_WORKSPACE>java TestRunner
检查运行结果
true
所有的断言都包含在 Assert 类中
public class Assert extends java.lang.Object
这个类提供了很多有用的断言方法来编写测试用例。只有失败的断言才会被记录。Assert 类中的一些有用的方法列式如下:
序号 | 方法和描述 |
---|---|
1 | void assertEquals(boolean expected, boolean actual) 检查两个变量或者等式是否平衡 |
2 | void assertTrue(boolean condition) 检查条件为真 |
3 | void assertFalse(boolean condition) 检查条件为假 |
4 | void assertNotNull(Object object) 检查对象不为空 |
5 | void assertNull(Object object) 检查对象为空 |
6 | void assertSame(Object expected, Object actual) assertSame() 方法检查两个相关对象是否指向同一个对象 |
7 | void assertNotSame(Object expected, Object actual) assertNotSame() 方法检查两个相关对象是否不指向同一个对象 |
8 | void assertArrayEquals(expectedArray, resultArray) assertArrayEquals() 方法检查两个数组是否相等 |
下面我们在例子中试验一下上面提到的各种方法。在 C: > JUNIT_WORKSPACE 路径下创建一个文件名为 TestAssertions.java 的类
import org.junit.Test;import static org.junit.Assert.*;public class TestAssertions { @Test public void testAssertions() { //test data String str1 = new String ("abc"); String str2 = new String ("abc"); String str3 = null; String str4 = "abc"; String str5 = "abc"; int val1 = 5; int val2 = 6; String[] expectedArray = {"one", "two", "three"}; String[] resultArray = {"one", "two", "three"}; //Check that two objects are equal assertEquals(str1, str2); //Check that a condition is true assertTrue (val1 < val2); //Check that a condition is false assertFalse(val1 > val2); //Check that an object isn't null assertNotNull(str1); //Check that an object is null assertNull(str3); //Check if two object references point to the same object assertSame(str4,str5); //Check if two object references not point to the same object assertNotSame(str1,str3); //Check whether two arrays are equal to each other. assertArrayEquals(expectedArray, resultArray); }}
接下来,我们在 C: > JUNIT_WORKSPACE 路径下创建一个文件名为 TestRunner.java 的类来执行测试用例
import org.junit.runner.JUnitCore;import org.junit.runner.Result;import org.junit.runner.notification.Failure;public class TestRunner2 { public static void main(String[] args) { Result result = JUnitCore.runClasses(TestAssertions.class); for (Failure failure : result.getFailures()) { System.out.println(failure.toString()); } System.out.println(result.wasSuccessful()); }}
用 javac 编译 Test case 和 Test Runner 类
C:JUNIT_WORKSPACE>javac TestAssertions.java TestRunner.java
现在运行将会运行 Test Case 类中定义和提供的测试案例的 Test Runner
C:JUNIT_WORKSPACE>java TestRunner
检查运行结果
true
注解就好像你可以在你的代码中添加并且在方法或者类中应用的元标签。JUnit 中的这些注解为我们提供了测试方法的相关信息,哪些方法将会在测试方法前后应用,哪些方法将会在所有方法前后应用,哪些方法将会在执行中被忽略。
JUnit 中的注解的列表以及他们的含义:
序号 | 注解和描述 |
---|---|
1 | @Test 这个注解说明依附在 JUnit 的 public void 方法可以作为一个测试案例。 |
2 | @Before 有些测试在运行前需要创造几个相似的对象。在 public void 方法加该注解是因为该方法需要在 test 方法前运行。 |
3 | @After 如果你将外部资源在 Before 方法中分配,那么你需要在测试运行后释放他们。在 public void 方法加该注解是因为该方法需要在 test 方法后运行。 |
4 | @BeforeClass 在 public void 方法加该注解是因为该方法需要在类中所有方法前运行。 |
5 | @AfterClass 它将会使方法在所有测试结束后执行。这个可以用来进行清理活动。 |
6 | @Ignore 这个注解是用来忽略有关不需要执行的测试的。 |
在 C: > JUNIT_WORKSPACE 路径下创建一个文件名为 JunitAnnotation.java 的类来测试注解
import org.junit.After;import org.junit.AfterClass;import org.junit.Before;import org.junit.BeforeClass;import org.junit.Ignore;import org.junit.Test;public class JunitAnnotation { //execute before class @BeforeClass public static void beforeClass() { System.out.println("in before class"); } //execute after class @AfterClass public static void afterClass() { System.out.println("in after class"); } //execute before test @Before public void before() { System.out.println("in before"); } //execute after test @After public void after() { System.out.println("in after"); } //test case @Test public void test() { System.out.println("in test"); } //test case ignore and will not execute @Ignore public void ignoreTest() { System.out.println("in ignore test"); }}
接下来,我们在 C: > JUNIT_WORKSPACE 路径下创建一个文件名为 TestRunner.java 的类来执行注解
import org.junit.runner.JUnitCore;import org.junit.runner.Result;import org.junit.runner.notification.Failure;public class TestRunner { public static void main(String[] args) { Result result = JUnitCore.runClasses(JunitAnnotation.class); for (Failure failure : result.getFailures()) { System.out.println(failure.toString()); } System.out.println(result.wasSuccessful()); }}
用 javac 编译 Test case 和 Test Runner 类
C:JUNIT_WORKSPACE>javac TestAssertions.java TestRunner.java
现在运行将会运行 Test Case 类中定义和提供的测试案例的 Test Runner
C:JUNIT_WORKSPACE>java TestRunner
检查运行结果
in before classin beforein testin afterin after classtrue
本教程阐明了 JUnit 中的方法执行过程,即哪一个方法首先被调用,哪一个方法在一个方法之后调用。以下为 JUnit 测试方法的 API,并且会用例子来说明。
在目录 C: > JUNIT_WORKSPACE 创建一个 java 类文件命名为 JunitAnnotation.java 来测试注释程序。
import org.junit.After;import org.junit.AfterClass;import org.junit.Before;import org.junit.BeforeClass;import org.junit.Ignore;import org.junit.Test;public class ExecutionProcedureJunit { //execute only once, in the starting @BeforeClass public static void beforeClass() { System.out.println("in before class"); } //execute only once, in the end @AfterClass public static void afterClass() { System.out.println("in after class"); } //execute for each test, before executing test @Before public void before() { System.out.println("in before"); } //execute for each test, after executing test @After public void after() { System.out.println("in after"); } //test case 1 @Test public void testCase1() { System.out.println("in test case 1"); } //test case 2 @Test public void testCase2() { System.out.println("in test case 2"); }}
接下来,让我们在目录 C: > JUNIT_WORKSPACE 中创建一个 java 类文件 TestRunner.java 来执行注释程序。
import org.junit.runner.JUnitCore;import org.junit.runner.Result;import org.junit.runner.notification.Failure;public class TestRunner { public static void main(String[] args) { Result result = JUnitCore.runClasses(ExecutionProcedureJunit.class); for (Failure failure : result.getFailures()) { System.out.println(failure.toString()); } System.out.println(result.wasSuccessful()); }}
使用 javac 命令来编译 Test case 和 Test Runner 类。
C:JUNIT_WORKSPACE>javac ExecutionProcedureJunit.java TestRunner.java
现在运行 Test Runner 它会自动运行定义在 Test Case 类中的测试样例。
C:JUNIT_WORKSPACE>java TestRunner
验证输出
in before classin beforein test case 1in afterin beforein test case 2in afterin after class
观察以上的输出,这是 JUnite 执行过程:
测试用例是使用 JUnitCore 类来执行的。JUnitCore 是运行测试的外观类。它支持运行 JUnit 4 测试, JUnit 3.8.x 测试,或者他们的混合。要从命令行运行测试,可以运行 java org.junit.runner.JUnitCore 。对于只有一次的测试运行,可以使用静态方法 runClasses(Class[])。
下面是 org.junit.runner.JUnitCore 类的声明:
public class JUnitCore extends java.lang.Object
/** This class prints the given message on console.*/public class MessageUtil { private String message; //Constructor //@param message to be printed public MessageUtil(String message){ this.message = message; } // prints the message public String printMessage(){ System.out.println(message); return message; } }
在目录 C: > JUNIT_WORKSPACE 创建一个 java 类文件命名为 TestJunit.java
import org.junit.Test;import static org.junit.Assert.assertEquals;public class TestJunit { String message = "Hello World"; MessageUtil messageUtil = new MessageUtil(message); @Test public void testPrintMessage() { assertEquals(message,messageUtil.printMessage()); }}
接下来,让我们在目录 C: > JUNIT_WORKSPACE 创建一个 java 类文件命名为 TestRunner.java 来执行测试用例,导出 JUnitCore 类并且使用 runClasses() 方法,将测试类名称作为参数。
import org.junit.runner.JUnitCore;import org.junit.runner.Result;import org.junit.runner.notification.Failure;public class TestRunner { public static void main(String[] args) { Result result = JUnitCore.runClasses(TestJunit.class); for (Failure failure : result.getFailures()) { System.out.println(failure.toString()); } System.out.println(result.wasSuccessful()); }}
使用 javac 命令来编译 Test case 和 Test Runner 类。
C:JUNIT_WORKSPACE>javac MessageUtil.java TestJunit.java TestRunner.java
现在运行 Test Runner 它会自动运行定义在 Test Case 类中的测试样例。
C:JUNIT_WORKSPACE>java TestRunner
验证输出
Hello Worldtrue
在实际项目中,随着项目进度的开展,单元测试类会越来越多,可是直到现在我们还只会一个一个的单独运行测试类,这在实际项目实践中肯定是不可行的。为了解决这个问题,JUnit 提供了一种批量运行测试类的方法,叫做测试套件。
这样,每次需要验证系统功能正确性时,只执行一个或几个测试套件便可以了。测试套件的写法非常简单,我们需要遵循以下规则:
package test;import org.junit.Assert;import org.junit.Test;/**类描述: *@author: zk *@date: 日期:2018-6-6 时间:下午3:56:17 *@version 1.0 */public class JunitTestOne { @Test public void test() { System.out.println("测试一。。。"); Assert.assertTrue(true); }}
package test;import org.junit.Assert;import org.junit.Test;/**类描述: *@author: zk *@date: 日期:2018-6-6 时间:下午3:58:56 *@version 1.0 */public class JunitTestTwo { @Test public void test() { System.out.println("测试二。。。"); Assert.assertTrue(true); }}
package test;import org.junit.runner.RunWith;import org.junit.runners.Suite;import org.junit.runners.Suite.SuiteClasses;/**类描述: *@author: zk *@date: 日期:2018-6-6 时间:下午4:00:06 *@version 1.0 */@RunWith(Suite.class)@SuiteClasses({ JunitTestOne.class,JunitTestTwo.class })public class AllTests {}
上例代码中,我将2个测试类放入了测试套件 AllTests 中,在 Eclipse 中运行测试套件,可以看到2个测试类被调用执行了。测试套件中不仅可以包含基本的测试类,而且可以包含其它的测试套件,这样可以很方便的分层管理不同模块的单元测试代码。
注意:一定要保证测试套件之间没有循环包含关系,否则无尽的循环就会出现在我们的面前。
有时可能会发生我们的代码还没有准备好的情况,这时测试用例去测试这个方法或代码的时候会造成失败。@Ignore 注释会在这种情况时帮助我们。
现在我们用例子来学习 @Ignore。
/** This class prints the given message on console.*/public class MessageUtil { private String message; //Constructor //@param message to be printed public MessageUtil(String message){ this.message = message; } // prints the message public String printMessage(){ System.out.println(message); return message; } // add "Hi!" to the message public String salutationMessage(){ message = "Hi!" + message; System.out.println(message); return message; } }
在目录 C: > JUNIT_WORKSPACE 中创建一个 java 类文件命名为 TestJunit.java
import org.junit.Test;import org.junit.Ignore;import static org.junit.Assert.assertEquals;public class TestJunit { String message = "Robert"; MessageUtil messageUtil = new MessageUtil(message); @Ignore @Test public void testPrintMessage() { System.out.println("Inside testPrintMessage()"); message = "Robert"; assertEquals(message,messageUtil.printMessage()); } @Test public void testSalutationMessage() { System.out.println("Inside testSalutationMessage()"); message = "Hi!" + "Robert"; assertEquals(message,messageUtil.salutationMessage()); }}
在目录 C: > JUNIT_WORKSPACE 创建一个 java 类文件叫做 TestRunner.java 来执行测试用例。
import org.junit.runner.JUnitCore;import org.junit.runner.Result;import org.junit.runner.notification.Failure;public class TestRunner { public static void main(String[] args) { Result result = JUnitCore.runClasses(TestJunit.class); for (Failure failure : result.getFailures()) { System.out.println(failure.toString()); } System.out.println(result.wasSuccessful()); }}
使用 javac 命令编译 MessageUtil, Test case 和 Test Runner 类。
C:JUNIT_WORKSPACE>javac MessageUtil.java TestJunit.java TestRunner.java
现在运行 Test Runner 类,即不会运行在 Test Case 类中定义的 testPrintMessage() 测试用例。
C:JUNIT_WORKSPACE>java TestRunner
验证输出。testPrintMessage() 测试用例并没有被测试。
Inside testSalutationMessage()Hi!Roberttrue
现在更新在目录 C: > JUNIT_WORKSPACE 中的 TestJunit 在类级别上使用 @Ignore 来忽略所有的测试用例
import org.junit.Test;import org.junit.Ignore;import static org.junit.Assert.assertEquals;@Ignorepublic class TestJunit { String message = "Robert"; MessageUtil messageUtil = new MessageUtil(message); @Test public void testPrintMessage() { System.out.println("Inside testPrintMessage()"); message = "Robert"; assertEquals(message,messageUtil.printMessage()); } @Test public void testSalutationMessage() { System.out.println("Inside testSalutationMessage()"); message = "Hi!" + "Robert"; assertEquals(message,messageUtil.salutationMessage()); }}
使用 javac 命令编译 Test case
C:JUNIT_WORKSPACE>javac TestJunit.java
保持你的 Test Runner 不被改变,如下:
import org.junit.runner.JUnitCore;import org.junit.runner.Result;import org.junit.runner.notification.Failure;public class TestRunner { public static void main(String[] args) { Result result = JUnitCore.runClasses(TestJunit.class); for (Failure failure : result.getFailures()) { System.out.println(failure.toString()); } System.out.println(result.wasSuccessful()); }}
现在运行 Test Runner 即不会运行在 Test Case 类中定义的任何一个测试样例。
C:JUNIT_WORKSPACE>java TestRunner
验证输出。没有测试用例被测试。
true
Junit 提供了一个暂停的方便选项。如果一个测试用例比起指定的毫秒数花费了更多的时间,那么 Junit 将自动将它标记为失败。timeout 参数和 @Test 注释一起使用。现在让我们看看活动中的 @test(timeout)。
/** This class prints the given message on console.*/public class MessageUtil { private String message; //Constructor //@param message to be printed public MessageUtil(String message){ this.message = message; } // prints the message public void printMessage(){ System.out.println(message); while(true); } // add "Hi!" to the message public String salutationMessage(){ message = "Hi!" + message; System.out.println(message); return message; } }
在 C:JUNIT_WORKSPACE 中创建一个文件名为 TestJunit.java 的 java 类。
import org.junit.Test;import org.junit.Ignore;import static org.junit.Assert.assertEquals;public class TestJunit { String message = "Robert"; MessageUtil messageUtil = new MessageUtil(message); @Test(timeout=1000) public void testPrintMessage() { System.out.println("Inside testPrintMessage()"); messageUtil.printMessage(); } @Test public void testSalutationMessage() { System.out.println("Inside testSalutationMessage()"); message = "Hi!" + "Robert"; assertEquals(message,messageUtil.salutationMessage()); }}
在 C:JUNIT_WORKSPACE 中创建一个文件名为 TestRunner.java 的 java 类来执行测试样例。
import org.junit.runner.JUnitCore;import org.junit.runner.Result;import org.junit.runner.notification.Failure;public class TestRunner { public static void main(String[] args) { Result result = JUnitCore.runClasses(TestJunit.class); for (Failure failure : result.getFailures()) { System.out.println(failure.toString()); } System.out.println(result.wasSuccessful()); }}
用 javac 编译 MessageUtil,Test case 和 Test Runner 类。
C:JUNIT_WORKSPACE>javac MessageUtil.java TestJunit.java TestRunner.java
现在运行 Test Runner,它将运行由提供的 Test Case 类中所定义的测试用例。
C:JUNIT_WORKSPACE>java TestRunner
验证输出。testPrintMessage() 测试用例将标记单元测试失败。
Inside testPrintMessage()RobertInside testSalutationMessage()Hi!RoberttestPrintMessage(TestJunit): test timed out after 1000 millisecondsfalse
Junit 用代码处理提供了一个追踪异常的选项。你可以测试代码是否它抛出了想要得到的异常。expected 参数和 @Test 注释一起使用。现在让我们看看活动中的 @Test(expected)。
/** This class prints the given message on console.*/public class MessageUtil { private String message; //Constructor //@param message to be printed public MessageUtil(String message){ this.message = message; } // prints the message public void printMessage(){ System.out.println(message); int a =0; int b = 1/a; } // add "Hi!" to the message public String salutationMessage(){ message = "Hi!" + message; System.out.println(message); return message; } }
在 C:> JUNIT_WORKSPACE 中创建一个文件名为 TestJunit.java 的 java 类
import org.junit.Test;import org.junit.Ignore;import static org.junit.Assert.assertEquals;public class TestJunit { String message = "Robert"; MessageUtil messageUtil = new MessageUtil(message); @Test(expected = ArithmeticException.class) public void testPrintMessage() { System.out.println("Inside testPrintMessage()"); messageUtil.printMessage(); } @Test public void testSalutationMessage() { System.out.println("Inside testSalutationMessage()"); message = "Hi!" + "Robert"; assertEquals(message,messageUtil.salutationMessage()); }}
在 C:> JUNIT_WORKSPACE 中创建一个文件名为 TestJunit.java 的 java 类来执行测试用例。
import org.junit.runner.JUnitCore;import org.junit.runner.Result;import org.junit.runner.notification.Failure;public class TestRunner { public static void main(String[] args) { Result result = JUnitCore.runClasses(TestJunit.class); for (Failure failure : result.getFailures()) { System.out.println(failure.toString()); } System.out.println(result.wasSuccessful()); }}
用 javac 编译 MessageUtil,Test case 和 Test Runner 类。
C:JUNIT_WORKSPACE>javac MessageUtil.java TestJunit.java TestRunner.java
现在运行 Test Runner,它将运行由提供的 Test Case 类中所定义的测试用例。
C:JUNIT_WORKSPACE>java TestRunner
验证输出。testPrintMessage() 测试用例将通过。
Inside testPrintMessage()RobertInside testSalutationMessage()Hi!Roberttrue
Junit 4 引入了一个新的功能参数化测试。参数化测试允许开发人员使用不同的值反复运行同一个测试。你将遵循 5 个步骤来创建参数化测试。
一旦每一行数据出现测试用例将被调用。让我们看看活动中的参数化测试。
public class PrimeNumberChecker { public Boolean validate(final Integer primeNumber) { for (int i = 2; i < (primeNumber / 2); i++) { if (primeNumber % i == 0) { return false; } } return true; }}
在 C:> JUNIT_WORKSPACE 中创建一个文件名为 PrimeNumberCheckerTest.java 的 java 类。
import java.util.Arrays;import java.util.Collection;import org.junit.Test;import org.junit.Before;import org.junit.runners.Parameterized;import org.junit.runners.Parameterized.Parameters;import org.junit.runner.RunWith;import static org.junit.Assert.assertEquals;@RunWith(Parameterized.class)public class PrimeNumberCheckerTest { private Integer inputNumber; private Boolean expectedResult; private PrimeNumberChecker primeNumberChecker; @Before public void initialize() { primeNumberChecker = new PrimeNumberChecker(); } // Each parameter should be placed as an argument here // Every time runner triggers, it will pass the arguments // from parameters we defined in primeNumbers() method public PrimeNumberCheckerTest(Integer inputNumber, Boolean expectedResult) { this.inputNumber = inputNumber; this.expectedResult = expectedResult; } @Parameterized.Parameters public static Collection primeNumbers() { return Arrays.asList(new Object[][] { { 2, true }, { 6, false }, { 19, true }, { 22, false }, { 23, true } }); } // This test will run 4 times since we have 5 parameters defined @Test public void testPrimeNumberChecker() { System.out.println("Parameterized Number is : " + inputNumber); assertEquals(expectedResult, primeNumberChecker.validate(inputNumber)); }}
在 C:> JUNIT_WORKSPACE 中创建一个文件名为 TestRunner.java 的 java 类来执行测试用例
import org.junit.runner.JUnitCore;import org.junit.runner.Result;import org.junit.runner.notification.Failure;public class TestRunner { public static void main(String[] args) { Result result = JUnitCore.runClasses(PrimeNumberCheckerTest.class); for (Failure failure : result.getFailures()) { System.out.println(failure.toString()); } System.out.println(result.wasSuccessful()); }}
用 javac 编译 PrimeNumberChecker,PrimeNumberCheckerTest 和 TestRunner 类。
C:JUNIT_WORKSPACE>javac PrimeNumberChecker.java PrimeNumberCheckerTest.javaTestRunner.java
现在运行 TestRunner,它将运行由提供的 Test Case 类中所定义的测试用例。
C:JUNIT_WORKSPACE>java TestRunner
验证输出。
Parameterized Number is : 2Parameterized Number is : 6Parameterized Number is : 19Parameterized Number is : 22Parameterized Number is : 23true
在这个例子中,我们将展示如何使用 ANT 运行 JUnit。让我们跟随以下步骤:
下载 Apache ANT
操作系统 | 文件名 |
---|---|
Windows | apache-ant-1.8.4-bin.zip |
Linux | apache-ant-1.8.4-bin.tar.gz |
Mac | apache-ant-1.8.4-bin.tar.gz |
设置 ANT_HOME 环境变量来指向 ANT 函数库在机器中存储的基本文件地址。例如,我们已经在不同的操作系统的 apache-ant-1.8.4 文件夹中存储了 ANT 函数库。
操作系统 | 输出 |
---|---|
Windows | 在 C:Program FilesApache Software Foundation apache-ant-1.8.4 中设置环境变量 ANT_HOME |
Linux | 导出 ANT_HOME=/usr/local/apache-ant-1.8.4 |
Mac | export ANT_HOME=/Library/apache-ant-1.8.4 |
附加 ANT 编译器地址到系统路径,对于不同的操作系统来说如下所示:
操作系统 | 输出 |
---|---|
Windows | 附加字符串 ;%ANT_HOMEin to the end of the system variable, Path. |
Linux | 导出 PATH=$PATH:$ANT_HOME/bin/ |
Mac | 不需要 |
操作系统 | 输出 |
---|---|
Windows | junit4.10.jar |
Linux | junit4.10.jar |
Mac | junit4.10.jar |
/** This class prints the given message on console.*/public class MessageUtil { private String message; //Constructor //@param message to be printed public MessageUtil(String message){ this.message = message; } // prints the message public String printMessage(){ System.out.println(message); return message; } // add "Hi!" to the message public String salutationMessage(){ message = "Hi!" + message; System.out.println(message); return message; } }
import org.junit.Test;import org.junit.Ignore;import static org.junit.Assert.assertEquals;public class TestMessageUtil { String message = "Robert"; MessageUtil messageUtil = new MessageUtil(message); @Test public void testPrintMessage() { System.out.println("Inside testPrintMessage()"); assertEquals(message,messageUtil.printMessage()); } @Test public void testSalutationMessage() { System.out.println("Inside testSalutationMessage()"); message = "Hi!" + "Robert"; assertEquals(message,messageUtil.salutationMessage()); }}
我们将使用 ANT 中的 任务来执行我们的 junit 测试样例。
<project name="JunitTest" default="test" basedir="."> <property name="testdir" location="test" /> <property name="srcdir" location="src" /> <property name="full-compile" value="true" /> <path id="classpath.base"/> <path id="classpath.test"> <pathelement location="/lib/junit-4.10.jar" /> <pathelement location="${testdir}" /> <pathelement location="${srcdir}" /> <path refid="classpath.base" /> </path> <target name="clean" > <delete verbose="${full-compile}"> <fileset dir="${testdir}" includes="**/*.class" /> </delete> </target> <target name="compile" depends="clean"> <javac srcdir="${srcdir}" destdir="${testdir}" verbose="${full-compile}"> <classpath refid="classpath.test"/> </javac> </target> <target name="test" depends="compile"> <junit> <classpath refid="classpath.test" /> <formatter type="brief" usefile="false" /> <test name="TestMessageUtil" /> </junit> </target></project>
运行下列的 ant 命令
C:JUNIT_WORKSPACETestJunitWithAnt>ant
验证输出。
Buildfile: C:JUNIT_WORKSPACETestJunitWithAntuild.xmlclean: compile: [javac] Compiling 2 source files to C:JUNIT_WORKSPACETestJunitWithAnt est [javac] [parsing started C:JUNIT_WORKSPACETestJunitWithAntsrc MessageUtil.java] [javac] [parsing completed 18ms] [javac] [parsing started C:JUNIT_WORKSPACETestJunitWithAntsrc TestMessageUtil.java] [javac] [parsing completed 2ms] [javac] [search path for source files: C:JUNIT_WORKSPACE TestJunitWithAntsrc] [javac] [loading javalangObject.class(javalang:Object.class)] [javac] [loading javalangString.class(javalang:String.class)] [javac] [loading orgjunitTest.class(orgjunit:Test.class)] [javac] [loading orgjunitIgnore.class(orgjunit:Ignore.class)] [javac] [loading orgjunitAssert.class(orgjunit:Assert.class)] [javac] [loading javalangannotationRetention.class (javalangannotation:Retention.class)] [javac] [loading javalangannotationRetentionPolicy.class (javalangannotation:RetentionPolicy.class)] [javac] [loading javalangannotationTarget.class (javalangannotation:Target.class)] [javac] [loading javalangannotationElementType.class (javalangannotation:ElementType.class)] [javac] [loading javalangannotationAnnotation.class (javalangannotation:Annotation.class)] [javac] [checking MessageUtil] [javac] [loading javalangSystem.class(javalang:System.class)] [javac] [loading javaioPrintStream.class(javaio:PrintStream.class)] [javac] [loading javaioFilterOutputStream.class (javaio:FilterOutputStream.class)] [javac] [loading javaioOutputStream.class(javaio:OutputStream.class)] [javac] [loading javalangStringBuilder.class (javalang:StringBuilder.class)] [javac] [loading javalangAbstractStringBuilder.class (javalang:AbstractStringBuilder.class)] [javac] [loading javalangCharSequence.class(javalang:CharSequence.class)] [javac] [loading javaioSerializable.class(javaio:Serializable.class)] [javac] [loading javalangComparable.class(javalang:Comparable.class)] [javac] [loading javalangStringBuffer.class(javalang:StringBuffer.class)] [javac] [wrote C:JUNIT_WORKSPACETestJunitWithAnt estMessageUtil.class] [javac] [checking TestMessageUtil] [javac] [wrote C:JUNIT_WORKSPACETestJunitWithAnt estTestMessageUtil.class] [javac] [total 281ms]test: [junit] Testsuite: TestMessageUtil [junit] Tests run: 2, Failures: 0, Errors: 0, Time elapsed: 0.008 sec [junit] [junit] ------------- Standard Output --------------- [junit] Inside testPrintMessage() [junit] Robert [junit] Inside testSalutationMessage() [junit] Hi!Robert [junit] ------------- ---------------- ---------------BUILD SUCCESSFULTotal time: 0 seconds
为了设置带有 eclipse 的 JUnit,需要遵循以下步骤。
下载 JUnit
操作系统 | 文件名 |
---|---|
Windows | junit4.10.jar |
Linux | junit4.10.jar |
Mac | junit4.10.jar |
假设你在 C:>JUnit 文件夹中复制了以上 JAR 文件。
现在你的 eclipse 已经准备好 JUnit 测试用例的开发了。
/** This class prints the given message on console.*/public class MessageUtil { private String message; //Constructor //@param message to be printed public MessageUtil(String message){ this.message = message; } // prints the message public String printMessage(){ System.out.println(message); return message; } }
import org.junit.Test;import static org.junit.Assert.assertEquals;public class TestJunit { String message = "Hello World"; MessageUtil messageUtil = new MessageUtil(message); @Test public void testPrintMessage() { assertEquals(message,messageUtil.printMessage()); }}
下面是项目结构
最后,通过右击程序和 run as junit 验证程序的输出。
验证结果
以下是 JUnit 扩展
Cactus 是一个简单框架用来测试服务器端的 Java 代码(Servlets, EJBs, Tag Libs, Filters)。Cactus 的设计意图是用来减小为服务器端代码写测试样例的成本。它使用 JUnit 并且在此基础上进行扩展。Cactus 实现了 in-container 的策略,意味着可以在容器内部执行测试。
Cactus 系统由以下几个部分组成:
这是使用 cactus 的样例代码。
import org.apache.cactus.*;import junit.framework.*;public class TestSampleServlet extends ServletTestCase { @Test public void testServlet() { // Initialize class to test SampleServlet servlet = new SampleServlet(); // Set a variable in session as the doSomething() // method that we are testing session.setAttribute("name", "value"); // Call the method to test, passing an // HttpServletRequest object (for example) String result = servlet.doSomething(request); // Perform verification that test was successful assertEquals("something", result); assertEquals("otherValue", session.getAttribute("otherName")); }}
JWebUnit 是一个基于 Java 的用于 web 应用的测试框架。它以一种统一、简单测试接口的方式包装了如 HtmlUnit 和 Selenium 这些已经存在的框架来允许你快速地测试 web 应用程序的正确性。
JWebUnit 提供了一种高级别的 Java API 用来处理结合了一系列验证程序正确性的断言的 web 应用程序。这包括通过链接,表单的填写和提交,表格内容的验证和其他 web 应用程序典型的业务特征。
这个简单的导航方法和随时可用的断言允许建立更多的快速测试而不是仅仅使用 JUnit 和 HtmlUnit。另外如果你想从 HtmlUnit 切换到其它的插件,例如 Selenium(很快可以使用),那么不用重写你的测试样例代码。
以下是样例代码。
import junit.framework.TestCase;import net.sourceforge.jwebunit.WebTester;public class ExampleWebTestCase extends TestCase { private WebTester tester; public ExampleWebTestCase(String name) { super(name); tester = new WebTester(); } //set base url public void setUp() throws Exception { getTestContext().setBaseUrl("http://myserver:8080/myapp"); } // test base info @Test public void testInfoPage() { beginAt("/info.html"); }}
XMLUnit 提供了一个单一的 JUnit 扩展类,即 XMLTestCase,还有一些允许断言的支持类:
我们假设有两个我们想要比较和断言它们相同的 XML 文件,我们可以写一个如下的简单测试类:
import org.custommonkey.xmlunit.XMLTestCase;public class MyXMLTestCase extends XMLTestCase { // this test method compare two pieces of the XML @Test public void testForXMLEquality() throws Exception { String myControlXML = "<msg><uuid>0x00435A8C</uuid></msg>"; String myTestXML = "<msg><localId>2376</localId></msg>"; assertXMLEqual("Comparing test xml to control xml", myControlXML, myTestXML); }}
在一个单元测试中,虚拟对象可以模拟复杂的,真实的(非虚拟)对象的行为,因此当一个真实对象不现实或不可能包含进一个单元测试的时候非常有用。
用虚拟对象进行测试时一般的编程风格包括:
以下是使用 Jmock 的 MockObject 例子。
import org.jmock.Mockery;import org.jmock.Expectations;class PubTest extends TestCase { Mockery context = new Mockery(); public void testSubReceivesMessage() { // set up final Sub sub = context.mock(Sub.class); Pub pub = new Pub(); pub.add(sub); final String message = "message"; // expectations context.checking(new Expectations() { oneOf (sub).receive(message); }); // execute pub.publish(message); // verify context.assertIsSatisfied(); }}