单元测试系列一:使用JUint进行单元测试
1. Junit简介
1.1 什么是JUnit
JUnit是一个Java语言的单元测试框架,由Erich Gamma和Kent Beck编写的一个回归测试的框架(regression testing framework)。多数Java开发工具都已经集成了JUnit作为单元测试的工具,它是xUnit的一个子集。
XUnit是一套基于测试驱动开发的测试框架,可以使我们快速的进行单元测试,家族成员有PythonUnit、CppUnit、JUnit。
1.2 特性
JUnit是一个开放源代码的Java测试框架,用于编写和运行可重复的测试,包括以下特性:
1)用于测试期望结果的断言(Assertion);
2)用于共享共同测试数据的测试工具;
3)用于方便的组织和运行测试的测试套件;
4)图形和文本的测试运行器。
1.3 JUnit3与JUnit4的区别
JUnit3需要在方法名前加test作为前缀。
JUnit3中所有的方法都必须使用@text注解。
JUnit3必须继承junit.framework.TestCase类。
1.4 为什么要使用JUnit
通常一个项目中有成千上万的方法,以前一般的做法是写一些测试代码看输出结果,然后由自己来判断结果是否正确,使用JUnit的好处就是这个结果是否正确的判断是由JUnit来完成的。我们只要关注结果是否正确就可以了。测试框架可以帮助我们对编写的程序进行有目的性的测试,减少代码中的bug,使用断言机制直接将预期结果与实际结果对比,确保对结果的可预知性。
1.5 JUnit中使用到jar包
jar包就是别人已经写好的一些类,然后将这些类进行打包,你可以将这些jar包引入到你的项目中,然后就可以直接使用这些jar包中的类和属性以及方法。
JUint包含:
junit.jar。
hamcrest-core.jar,设置匹配性规则的一个框架,可以有效增强JUnit测试的能力。
2. JUnit的基本过程
2.1 如何开发测试用例
eclipse中包含JUnit的测试框架,所以不需要单独下载jar包,我们可以使用Eclipse进行单元测试。
1)首先,我们需要创建一个被测试类,打开选项eclipse,选择File>>New>>Java Project,在Project Name中输入项目名称,例:junit4Demo,点击“Finish”,如下图所示:
2) 创建好的项目在Project Explorer中显示,如下图所示:
3) 项目名称右键>>New>>Package,在Name中输入包名,例:com.util,点击“Finish”,如下图所示:
4) 创建好的包显示在项目的src目录下,如下图所示:
5) 包名右键>>New>>Class,在Name中输入类名,例:Calculate,点击“Finish”,如下图所示:
6) 被测试类创建好后,如下图所示:
7) 被测试类包含加减乘除的运算的四个方法,所以添加代码如下:
package com.util;
public class Calculate {
public int add(int a,int b){
return a+b;
}
public int subtract(int a,int b){
return a-b;
}
public int multiply(int a,int b){
return a*b;
}
public int divide(int a,int b){
return a/b;
}
}
8) 接下来导入JUnit的jar包,项目右键>>Build Path>>Configure Bulid Path,如下图所示:
9) 选择Libraries>>Add Library>>JUnit>> JUnit4,点击“Finish”,点击“OK”, JUnit的jar包被导入项目中,如下图所示:
10) 为了保证源代码与测试代码的分离,查找起来方便,可以在src目录下创建test目录,src右键>>New>>Source Folder,Folder Name设置为“test”,点击“Finish”,如下图所示:
11) 创建好的目录显示在src目录下,如下图所示:
12) 包名右键>>New>>JUnit Test Cas,Name输入“CalculateTest”,选择Source folder为“test”点击 “Finish”,如下图所示:
13) 这个测试类会自动为我们生成一个测试方法的模板,如下图所示:
14) 在测试类中添加加减乘除四个方法的被测试代码,在测试过程中我们经常用到的断言方法有:assertEquals方法,该方法可以判断actualValue(实际值)与expectedValue(期望值)是否一致,如果两者不一致,则会抛出java/lang.AssertionError错误,打印出message(如果参数中有message的话),并跳出这个测试方法,下面的测试方法就是用这个方法去判断预期值与 实际值是否一致,如下图所示:
package com.util;
import static org.junit.Assert.*;
import org.junit.Test;
public class CalcuateTest {
@Test
public void testAdd() {
assertEquals(6,new Calculate().add(4, 2));
}
@Test
public void testSubtract() {
assertEquals(2,new Calculate().subtract(4, 2));
}
@Test
public void testMultipy() {
assertEquals(8,new Calculate().multiply(4, 2));
}
@Test
public void testDivide() {
assertEquals(6,new Calculate().divide(2, 4));
}
}
15) 被测试类名右键>>Run As>>JUnit Test,选择测试类,点击“OK”,打开JUnit视图,我们可以看到四个测试方法全部通过,如下图所示:
2.2 介绍 JUnit视图
Runs:总共介个测试方法/运行方法的个数;
Errors:抛出异常方法的计数器,是由代码异常引起的,它可以产生于测试代码本身的错误,也可能是被测试代码中一个隐藏的bug;
Failures:失败方法的计数器,一般单元测试中使用断言方法判断失败所引起的,这表示测试点发现了问题,就是谁程序输出结果和我们预期的不一样;
状态条:绿色代表成功,红色代表失败;
空白区域:本次运行方法或类的个数;
总结:
1)测试方法前必须使用@Test进行修饰;
2)测试方法使用public void进行修饰,不能带任何参数;
3)新建一个源代码目录来存在我们的测试代码;
4)测试类的包应该和被测试类保持一致;
5)测试单元中的每个方法可以独立测试,测试方法间不能有任务的依赖;
6)测试类使用Test作为类名的后缀(不是必须);
7)测试方法使用test作为方法名的前缀(不是必须)。
3. JUnit的使用详解
3.1 JUnit的运行流程
1) 创建一个测试方法,在JUnit Test Case页面中输入Name为“JunitFlowTest”,并选中页面下方的四个方法,点击“Finish”,如下图所示:
2) 新建的测试类中自动生成这个方法的模板,我们会发现这四个方法并没有使用@Test进行修饰,而是分别使用的@BeforeClass、@Before、@After、@AfterClass进行修饰,如下图所示:
3) 我们在每个测试方法中打印一句话,在写两个使用@Test修饰的方法,代码如下:
package com.util;
import static org.junit.Assert.*;
import org.junit.After;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
public class JunitFlowTest {
@BeforeClass
public static void setUpBeforeClass() throws Exception {
System.out.println("this is beforeClass...");
}
@AfterClass
public static void tearDownAfterClass() throws Exception {
System.out.println("this is afterClass...");
}
@Before
public void setUp() throws Exception {
System.out.println("this is before...");
}
@After
public void tearDown() throws Exception {
System.out.println("this is after...");
}
@Test
public void test1() {
System.out.println("this is test1...");
}
@Test
public void test2() {
System.out.println("this is test2...");
}
}
4) 运行测试类,查看运行结果:
总结:
1) @BeforeClass修饰的方法会在所有方法前被调用前执行,而且该方法是静态的,所以当测试类加载后接着就会运行它,而且在内存中它只会存在一份实例,它比较适合加载配置文件;
2) @AfterClass所修饰的方法通常用来对资源的清理,如关闭数据库链接;
3) @Before和@After会在每个测试方法前各执行一次,通过被称之为固定代码的意思,意思就是一定会执行的代码段。
3.2 常用注解
@Test是将一个普通的方法修饰为测试方法,Test有两个属性:
1.@Test(expected=xx.class)
1) 创建一个测试方法,在JUnit Test Case页面中输入Name为“AnotationTest”,,点击“Finish”,在类中添加如下代码:
package com.util;
import static org.junit.Assert.*;
import org.junit.Ignore;
import org.junit.Test;
public class AnotationTest {
@Test(expected=ArithmeticException.class)
public void testDivide() {
assertEquals(3,new Calculate().divide(6,0));
}
}
2) 运行后查看JUnit视图,观察测试结果,我们可以发现测试结果通过,没有报错,如果处理异常的代码删除掉就会出错,因为添加这个属性后,预期会抛出一个算数异常,可以捕获这个异常,如下图所示:
2.@Test(timeout=毫秒)
1) 在AnotationTest类中修改代码如下:
package com.util;
import static org.junit.Assert.*;
import org.junit.Ignore;
import org.junit.Test;
public class AnotationTest {
@Test(timeout=2000)
public void testWhile(){
while(true){
System.out.println("run forever");
}
}
}
2) 运行后查看运行结果,如下图所示,发现没有一直循环下去,在2s时自动结束循环,可以用它来做一些简单的性能测试,比如说读取一个文件,可以设置超时时间,如果超过这个时间可以认为测试不成功。
@Ignore所修饰的方法会被测试运行器忽略
1) 在AnotationTest类中修改代码如下:
package com.util;
import static org.junit.Assert.*;
import org.junit.Ignore;
import org.junit.Test;
public class AnotationTest {
@Ignore
@Test(timeout=2000)
public void testWhile(){
while(true){
System.out.println("run forever");
}
}
}
2) 运行后查看运行结果,如下图所示,在JUnit视图中可以看到这个方法并没有被执行,该方法会被测试运行器所忽略。
3.3 JUint测试套件的使用
在测试过程中,随着项目的深入,项目的规模会越来越大,相应的测试类也会越来越多,那么会如果100个测试类,是不是就要运行100次,JUnit为我们提供了一个批量运行的测试类的方法,叫做测试套件,使用测试套件我们可以将所有的测试类都集合在一个测试套件中,这样每次需要验证系统功能的时候,只需要执行一次我们的测试套件就可以了。
如何编写测试套件?
1)创建一个测试类,命名为SuiteTest,测试套件有一个特点,它是一个空类,所以我们将默认的test()方法删除掉,如下图所示:
2)我们在再新建两个测试类,分别为TaskTest1,TaskTest2,打印一句话,如下图所示:
3)需要使用@RunWith这个注解,修改测试运行器,将其修改为Suite.class,这样这个类就成为测试套件的入口类,然后使用Suite.SuiteClass(),需要放入测试套件的测试类(或测试套件),它是以数组的形式作为参数,编写的代码如下图所示:
package com.util;
import static org.junit.Assert.*;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Suite;
@RunWith(Suite.class)
@Suite.SuiteClasses({TaskTest1.class,TaskTest2.class})
public class SuiteTest {
}
4)运行结果如下,可以看到TaskTest1.class、TaskTest2.class都运行了。
总结:
1) @RunWith可以更改测试运行器,本次测试套件中更改测试运行为Suite.class;
2) 测试套件就是组织测试类一起运行的;
3) 写一个作为测试套件的入口类,这个类里不包含其他的方法;
4) 将要测试的类作为数据传入Suite.SuiteClass({}).
3.4 JUnit参数化设置
为了提高测试代码的可重用度,在JUnit4中提供了参数化测试可以解决这个问题,下面看一下参数设置的步骤:
1)创建一个测试类,名称为ParameterTest,将自动生成的测试方法的代码删除,如下图所示:
2)更改测试运行器,更改为Parameterized;
3)声明变量来存放预期值和测试数据;
4)为测试类声明一个返回值为Collection的公共静态方法;
5)需要一个数组类型来存放多组数据,添加@Paramters注解;
6)为测试类声明一个带有参数的公共的构造函数;
7)还有写一个对加法测试的方法,整体的测试代码如下:
import static org.junit.Assert.*; import java.util.Arrays; import java.util.Collection; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.Parameterized; import org.junit.runners.Parameterized.Parameters; @RunWith(Parameterized.class) public class ParameterTest { int expected=0; int input1=0; int input2=0; @Parameters public static Collection<Object[]> t(){ return Arrays.asList(new Object[][]{ {3,1,2}, {4,2,2} }); } public ParameterTest(int expected,int input1,int input2){ this.expected=expected; this.input1=input1; this.input2=input2; } @Test public void testAdd(){ assertEquals(expected,new Calculate().add( input1,input2)); }
8)结果如下图所示,可以看到对加法进行了两组数据测试,使用这种方法可以对多组数据同时进行测试。
总结:
1)更改默认的测试运行器为RunWith(Parameterized.class);
2)声明变量来存放预期值和结果值;
3)声明一个返回值为Collection的公共静态方法,并使用@Parameters进行修饰;
4)为测试类声明一个带有参数的公共构造函数,并在其中为之声明变量赋值。
4. Eclipse的安装
4.1 Windows下Eclipse的安装
1.安装Eclipse之前,需要安装java sdk,并将java的路径配置到系统路径中。
1) 首先下载如jak 1.6的版本,然后进行解压,如图:
2) 打开jdk-6u39-windows-i586-20151102\jdk-6u39-windows-i586目录,运行“jdk-6u39-windows-i586.exe”,如图:
3) 点击“下一步”,进入自定义安装界面,如图:
4) 点击“下一步”,进入安装目标文件夹,如图:
5) 点击“下一步”,进入安装进度页面,如图:
6) 安装完成后,点击“完成”,安装完成。
7) 安装完成后需要设置环境变量后编译器才能正常使用,找到jdk安装路径C:\Program Files\Java\jdk1.6.0_39,然后右键“我的电脑>>属性高级>>环境变量”,打开“环境变量”对话框,如图:
8) 在系统变量里点击新建,变量名称写JAVA_HOME,变量值填写JDK的安装路径C:\Program Files\Java\jdk1.6.0_39,如图:
9) 在系统变量里点击新建,变量名称填写CLASSPATH,变量值填写“.;%JAVA_HOME%\lib;%JAVA_HOME%\lib\tools.jar”,如图:
10) 在系统变量里找打Path变量,这是系统自带的,不用新建。双击Path,由于原来的变量值已经存在,故应在已有的变量后加上“;%JAVA_HOME%\bin;%JAVA_HOME%\jre\bin”。如图:
11) 环境变量配置完毕,验证的方法:在运行框中输入cmd命令,回车输入java,按回车出现以下画面,如图:
12) 输入javac,安回车出现以下画面,则表示设置成功,如图:
2.下载Eclipse时注意系统的位数是32位还是64位的。
1) 下载完成后进行解压,然后双击eclipse.exe进行安装,如下图所示:
2) 安装过程完成后,直接打开Ide窗口,如下图所示:
4.2 Linux下Eclipse的安装
1 安装Eclipse之前,需要安装java sdk,并将java的路径配置到系统路径中。
1) 将压缩包解压到指定的安装目录,比如/usr,如下图所示:
2) 此时生成名为jdk1.8.0_20的目录,将其重命名为jdk,这一步是可选的,如下图所示:
3) 修改/etc/profile文件,添加环境变量,如下图所示:
4) 在文末添加下面的内容(需根据个人JDK实际安装位置进行配置),如下图所示:
5) 让/etc/profile文件修改后立即生效 ,可以使用如下命令(注意"."和"/"之间的空格),如下图所示:
6) 验证Jdk安装成功,查看一下Java版本,如下图所示:
2 下载Eclipse时注意系统的位数是32位还是64位的。
1) 进入到Eclipse存放路径,并进行解压,如下图所示:
2) 切换到安装包的目录,进行安装,如下图所示:
3) 选择“Eclipse Platform”,点击“Next”, 如下图所示:
4) 点击“Next”, 如下图所示:
5) 点击“Finish”, 如下图所示:
6) 等待安装,如下图所示:
7) 点击“Finish”,完成安装,如下图所示:
8) 在安装目录运行Eclipse,显示如下图,成功安装!如下图所示: