Junit(单元测试框架)(实例代码:JUnitTest)
我们在开发过程中需要写那么多业务代码,还为什么要写测试代码?
事实上,写测试代码对代码进行单元测试,并不是增加了工作量,恰恰相反,是减少了工作量,单元测试代码的出现,方便我们后期更好的维护项目代码,减少了很大工作量。
现在就先来说一下Junit4的学习********************
Junit4快速入门
Junit简介
什么是Junit?
先在浏览器中输入junit官网地址: junit.org
Junit是xUnit的一个分支子集,是一套可复用的Java单元测试框架。
xUnit是一套基于测试驱动开发(TDD)的测试框架,在c++,paython,java语言中测试框架的名字都不相同,分别衍生的产品有jUnit、pythonUnit、cppUnit 等
在项目中需要两种包:Junit.jar和hamcrest-core.jar
hamcrest-core设置匹配集规则的框架,可用来增强junit的功能。
Notes: Junit3和JUnit4的区别
JUnit3:必须继承junit.framework.TestCase这个类,在方法前面必须加上test最为前缀。
初始化资源的方法必须命名为setUp(),释放资源的方法必须被命名为tearDown(),
JUnit4:只要加上@Test注解即可,不需要继承任何类,对方法命名没有限制。
(官网中Java Docs有对Junit4API的说明)
为什么使用Junit?
好了,回头继续说这个问题:为什么要使用JUnit方法?
一个项目中的方法很多时候,夸张点说,成千上万,但是我们怎样确保每个方法执行出我们想要的结果呢,即,确保这个方法的正确性。
一个基本的方法,就是我们在一个Main类中写这些方法的测试代码,一个一个打印出我们我们每个方法的执行结果,但是这种方法枯燥无味,其缺点显而易见,各种方法不能一起运行,运行结果,需要程序员自行观察比对,特别麻烦。
Junit提供了一个断言机制:将程序预期的结果与程序运行的最终结果进行比对,确保对结果的可预知性,这样更加方便。
如何开发测试用例?
1 在Eclipse中建立一个Java项目
2 写一个测试类Calculate.java
3 引入JUnit测试包
右击项目名称-》Build Path-》Add Library-》添加JUnit包
4 建立JUnit测试类。NewàJUnit Test Case,创建的测试类会自动创建一个测试方法模板,此时可以模仿改模板重写对方法写测试类。
import static org.junit.Assert.*;
import org.junit.Test;
public class CalculateTest {
@Test
publicvoid test() {
fail("Notyet implemented");
}
}
照着模板写一个测试方法:
注意:JUnit4只需要用@Test注解声明测试单元,对测试方法命名没有严格规定;
assertEquals()方法中6是预期结果,newCalculate().add(2, 3)是测试目标。
测试:右击测试方法—》Run As -->JUnit Test;
测试结果如下图:
测试视图介绍:
Runs:1/1,表示只有一个测试用例,也执行了一个测试用例
Errors表示抛出异常的测试方法计数器
Failures表示执行失败的测试方法计数器,这个地方表示有一个测试方法执行失败,对应的下面方框中的add()方法前面相应的出现了叉叉;
下面的状态条如果是绿色,表示测试成功,预期值和测试结果相同;如果是红色表示测试失败。下面的空白框表示测试的类和测试方法。
Junit使用详解
在项目中使用JUnit测试的时候,最好不要把JUnit测试类和业务代码放在一起,一般在src目录下建立一个Source folder包test存放测试类,以后发布项目的时候可以删掉这个测试包。
自动生成测试类
右击被测试类—》new -->JUnit Test Case—》将SourceFolder中的src修改为test包名—》next--》选中要测试的方法—》Finish。
根据上面的测试类的书写,规范的测试代码可以总结为如下几条:
1) 测试方法必须使用@Test进行修饰
2) 测试方法必须使用public void 进行修饰,不能带任何的参数
3) 新建一个源代码目录来存放我们的测试代码
4) 测试类的报应该和被测试类保持一致。
5) 测试单元中每个测试方法必须可以独立测试,测试方法之间不能有任何依赖。
6) 测试类中使用Test作为类名的后缀(非必须)
7) 测试方法使用test作为方法名的前缀(非必需)
测试失败的两种情况
Failure一般由单元测试使用的断言方法判断失败所引起的,这经表示测试电发现了问题,就是说程序输出的结果和我们预期的不一样。
Error是由代码异常引起的,它可以产生测试代码本身的错误,也可以是被测试代码中隐藏的Bug;
测试用例不是用来证明被测试类是对的,而是证明它没有错误。
JUnit运行流程
根据测试类运行结果看测试流程:
publicclass CalculateTest3{
@BeforeClass
publicstaticvoidsetUpBeforeClass()throws Exception {
System.out.println("this is beforeClass……");
}
@AfterClass
publicstaticvoidtearDownAfterClass()throws Exception {
System.out.println("this is afterClass……");
}
@Before
publicvoidsetUp()throws Exception {
System.out.println("this is before……");
}
@After
publicvoidtearDown()throws Exception {
System.out.println("this is after……");
}
@Test
publicvoidtest1(){
System.out.println("this is Test1……");
}
@Test
publicvoidtest1(){
System.out.println("this is Test1……");
}
}
1) @BeforeClass在所有方法运行前执行的,该方法是静态的,所以,当测试类别加载后接着就会运行它,而且在内存中,它只会存在一份实例,它比较适合加载配置文件。
2) @AfterClass,所修饰的方法通常用来对资源进行清理,如关闭数据库的连接
3) @Before和@After会在每个测试方法前后各执行一次。
JUnit常用注解
/*
*@Test将一个方法修饰成测试方法
* @Test(excepted=XX.class)
* @Test(timeout=毫秒)
*@BeforeClass他会在所有的方法运行前被执行,static修饰
*@AfterClass 他会在所有的方法结束后背自行,static修饰
*@Before会在每一个测试方法被运行前执行一次
*@After 会在每一个测试方法运行后背执行一次。
*@Ignore所修饰的方法会被测试运行器忽略后面可以加上 ("忽略说明内容")
*@RunWith:可以更改测试运行器 org.junit.runner.Runner
*/
publicclass AnnotationTest{
/*
*expected=ArithmeticException.class表示预期抛出异常,运行达到运行结果,表示运行成功。
*/
@Test(expected=ArithmeticException.class)
publicvoidtestAdd()
{
assertEquals(3,newCalculate().divide(6, 0));
}
/*
*@Test(timeout=2000) 表示测试执行在2s内循环执行,超出该时间段则循环停止,表示测试可能出现的错误执行得到终止。
*/
@Ignore("这个方法不能被执行")
@Test(timeout=2000)
publicvoidtestWhile()
{
while(true)
{
System.out.println("runforever……");
}
}
/*
* 测试只执行两秒。
*/
@Test(timeout=3000)
publicvoidtestReadFile()
{
try{
Thread.sleep(2000);
}
catch(InterruptedExceptione){
e.printStackTrace();
}
}
}
Junit4的深入使用
测试套件的运行
当测试类太多的时候,我们一个一个执行,这样会比较麻烦,为了节省时间,我们使用JUnit4测试套件,将需要的测试类的集合在测试套件中。
import org.junit.runner.RunWith;
import org.junit.runners.Suite;
@RunWith(Suite.class)//修改测试运行期,表示这是测试套件类的入口
@Suite.SuiteClasses(value={ TaskTest1.class,TaskTest2.class,TaskTest3.class})
publicclass SuiteTest{
/*
* 保证测试套件为空,运行添加的所有测试类。
* 测试套件就是组织测试类一起运行的
* 需要写一个测试套件的入口类,这个类里不包含其他的方法
* 更改测试运行器的Suite.class
* 将要测试的类作为数组传入到Suite.SuiteClasses
*/
}
- * 保证测试套件为空,运行添加的所有测试类。
- * 测试套件就是组织测试类一起运行的
- * 需要写一个测试套件的入口类,这个类里不包含其他的方法
- * 更改测试运行器的Suite.class
- * 将要测试的类作为数组传入到Suite.SuiteClasses
Junit4的参数化设置
@RunWith(Parameterized.class)
publicclass ParameterTest{
intexpected=0;
intinput1= 0;
intinput2= 0;
@Parameters
publicstatic Collection<Object[]>t(){
return Arrays.asList(
new Object[][]{
{3,1,2},
{4,2,2}
});
}
publicParameterTest(intexpected,intinput1,intinput2){
this.expected= expected;
this.input1= input1;
this.input2= input2;
}
@Test
publicvoidtestAdd(){
assertEquals(expected,newCalculate().add(input1,input2));
}
}
参数设置总结:
1.更改默认的测试运行器为@RunWith(Parameterized.class)
2.声明变量来存放预期值和结果值
3.声明一个返回值为Collection的公共静态方法,并使用@Parameter进行修饰
4.为测试类声明一个带有参数的公共构造函数,并在其中位置声明变量赋值。