笔者最近刚入职新公司,在公司熟悉业务以及公司所用的一些框架,正好学习到了JUnit框架,借此机会整理了一些东西。
1.JUnit介绍
JUnit 是一个 Java 编程语言的单元测试框架。JUnit 在测试驱动的开发方面有很重要的发展,是起源于 JUnit 的一个统称为 xUnit 的单元测试框架之一。
JUnit 促进了“先测试后编码”的理念,强调建立测试数据的一段代码,可以先测试,然后再应用。这个方法就好比“测试一点,编码一点,测试一点,编码一点……”,增加了程序员的产量和程序的稳定性,可以减少程序员的压力和花费在排错上的时间。
2.特点
- JUnit是一个开放的资源框架,用于编写和运行测试
- 提供注释来识别测试方法
- 提供断言来测试预期结果
- 提供测试运行来运行测试
- JUnit测试允许你编写代码更快,并能提高质量
- JUnit优雅简洁,没那么复杂,花费时间更少
- Junit测试可以自动运行并且检查自身结果并提供即时反馈,所以也没有必要人工梳理测试结果的报告
- JUnit测试可以被组织为测试套件,包含测试用例,甚至其他的测试套件
- JUnit在一个条中显示进度。如果运行良好则是绿色;如果运行失败,则变成红色
3.什么是一个单元测试用例?
单元测试用例是一部分代码,可以确保另一端代码(方法)按照预期工作。为了迅速达到预期的结果,就需要测试框架。JUnit是java编程语言理想的单元测试框架。
一个正式的编写好的单元测试用例的特点是:已知输入和预期输出,即在测试执行前就已知。已知输入需要测试的先决条件,预期输出需要测试后置条件。
每一项需求至少需要两个单元测试用例:一个正检验,一个负检验。如果一个需求有子需求,每一个子需求必须至少有正检验和负检验两个测试用例。
4.JUnit-测试框架
4.1 什么是JUnit测试框架?
JUnit是一个回归测试框架,被开发者用于实施对应用程序的单元测试,加快程序编制速度,同时提高编码的质量。JUnit测试框架能够轻松完成以下任意两种结合:
- Eclipse集成开发环境
- Ant打包工具
- Maven项目构建管理
4.2 特性
JUnit测试框架具有以下重要特性:
- 测试工具
测试工具是一整套固定的工具用于基线测试。测试工具的目的是为了确保测试能够在共享且固定的环境中运行,因此保证测试结果的可重复性。它包括:- 在所有测试调用指令发起前的setUp()方法。
- 在测试方法运行后tearDown()方法。
- 测试套件
测试套件意味捆绑几个测试案例并且同时运行。在JUnit中,@RunWith和@Suite都被用作测试套件。 - 测试运行器
测试运行器用于执行测试案例。 - 测试分类
测试分类是在编写和测试JUnit的重要分类。几种重要的分类如下:- 包含一套断言方法的测试断言
- 包含规定运行多重测试工具的测试用例
- 包含收集执行测试用例结果的方法的测试结果
5.JUnit-API
JUnit中的最重要的程序包是junit.framework,它包含了所有的核心类。
5.1 Assert类(assert方法的集合)
public class Assert extends java.lang.Object
这个类提供了一系列的编写测试的有用的声明方法。只有失败的声明记录才会被记录,重要的方法如下一些:
- void assertEquals(boolean expected,boolean actual) 检查两个变量或者等式是否平衡
- void assertFalse(boolean condition)检查条件是假的
- void assertNotNull(Object object) 检查对象不是空的
- void assertNull(Object object) 检查对象是空的
- void assertTrue(boolean condition) 检查条件为真
- void fail() 在没有报告的情况下使测试不通过
5.2 TestCase类
public abstract class TestCase extends Assert implements Test
测试样例定义了运行多重测试的固定格式。TestCase 类的一些重要方法列式如下:
- int countTestCases() 为被run(TestResult result)执行的测试案例计数
- TestResult createResult() 创建一个默认的TestResult对象
- String getName() 获取TestCase的名称
- TestResult run() 一个运行这个测试的方便的方法,收集由TestResult对象产生的结果
- void run(TestResult result) 在TestResult中运行测试案例并收集结果
- void setName(String name) 设置TestCase的名称
- void setUp() 创建固定装置,例如打开一个网络连接
- void tearDown() 拆除固定装置,例如,关闭一个网络连接
- String toString() 返回测试案例的一个字符串表示
5.3 TestResult类
public class TestResult extends Object
TestResult 类收集所有执行测试案例的结果。它是收集参数层面的一个实例。这个实验框架区分失败和错误。失败是可以预料的并且可以通过假设来检查。错误是不可预料的问题就像 ArrayIndexOutOfBoundsException。TestResult 类的一些重要方法列式如下:
- void addError(Test test,Throwable t) 在错误列表加入一个错误
- void addFailure(Test test,AssertionFailedError t)在失败列表中加入一个失败
- void endTest(Test test) 显示测试被编译的这个结果
- int errorCount()获取被检测出错误的数量
- Enumeration errors() 返回错误的详细信息
- int failureCount() 获取被检测出的失败的数量
- void run(TestCase test)运行 TestCase
- int int runCount() 获得运行测试的数量
- void startTest(Test test) 声明一个测试即将开始
- void stop()标明测试必须停止
5.4 TestSuite类
public class TestSuite extends Object implements Test
TestSuite 类是测试的组成部分。它运行了很多的测试案例。TestSuite 类的一些重要方法列式如下:
- void addTest(Test test) 在套中加入测试
- void addTestSuite(Class<?extends TestCase>testClass) 将已经给定的类中的测试加到套中
- int countTestCases() 对这个测试即将运行的测试案例进行计数。
- String getName() 返回套的名称
- void run(TestResult result) 在TestResult中运行测试并收集结果
- void setName(String name) 设置套的名称
- Test testAt(int index) 给定的目录中返回测试
- int testCount() 返回套中测试的数量
- static Test warning(String message) 返回会失败的测试并且记录警告信息
6.JUnit-注释
注释就好像你可以在你的代码中添加并且在方法或者类中应用的元标签。JUnit 中的这些注释为我们提供了测试方法的相关信息,哪些方法将会在测试方法前后应用,哪些方法将会在所有方法前后应用,哪些方法将会在执行中被忽略。
JUnit 中的注释的列表以及他们的含义:
6.1 @Test
这个注释说明依附在 JUnit 的 public void 方法可以作为一个测试案例。
6.2 @Before
有些测试在运行前需要创造几个相似的对象。在 public void 方法加该注释是因为该方法需要在 test 方法前运行。
6.3 @After
如果你将外部资源在Before方法中分配,那么你需要在测试运行后释放他们。在 public void 方法加该注释是因为该方法需要在 test 方法后运行。
6.4 @BeforeClass
在 public void 方法加该注释是因为该方法需要在类中所有方法前运行。
6.5 @AfterClass
它将会使方法在所有测试结束后执行。这个可以用来进行清理活动。
6.6 @Ignore
这个注释是用来忽略有关不需要执行的测试的。
7.JUnit-执行过程
7.1 创建一个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");
}
}
7.2 创建一个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());
}
}
7.3 输出
in before class
in before
in test case 1
in after
in before
in test case 2
in after
in after class
7.4 JUnit执行过程:
- beforeClass()方法首先执行,并且只执行一次
- afterClass()方法最后执行,并且只执行一次
- before()方法针对每一个测试用例的执行,但是是在执行测试用例之前
- after()方法针对每一个测试用例的执行,但是是在执行测试用例之后
- 在before()方法和after()方法之间,执行每一个测试用例