Java 单元测试利器之 Junit

标签: java 单元测试 junit | 发表时间:2013-01-19 23:49 | 作者:鼠标CHH
出处:http://www.cnblogs.com/

       前言:

          因为工作和学习的需要,在代码中查错的时候,第一步就是想知道这个错误具体发生在一个位置,进行一个准确的定位。而这个定位的工作交给谁来做了呢?不难猜出也就是这篇博客的主题---Junit。junit是一个开源的框架,也是java这一块的测试工具之一。想了解详细请上官网,下面用代码来跟大家解释。

         准备要测试的方法,放进一个类中方便于测试。

package com.junit3_8;

/**
* junt3.8单元测试
*
* @author CHH
* @since 2013-01-19
*
*/
public class Calculator {

// 加
public int add(int a, int b) {

int sum=0;
for(int i=0;i<100;i++){
sum +=i;

}
System.out.println("加=="+sum);
return a+b;
}

// 减
public int subtract(int a, int b) {
int sum=0;
for(int i=0;i<100;i++){
sum +=i;

}
System.out.println("减=="+sum);
return a - b;
}

// 乘
public int multiply(int a, int b) {
int sum=0;
for(int i=0;i<100;i++){
sum +=i;

}
System.out.println("乘==="+sum);
return a * b;
}

// 除
public int divide(int a, int b) throws Exception {
int sum=0;
for(int i=0;i<100;i++){
sum +=i;

}
System.out.println("除==="+sum);

if (0 == b) {
throw new Exception("除数不能为0");
}
return a / b;
}
}

        Junit3.8测试类

package com.junit3_8;

import junit.framework.Assert;
import junit.framework.TestCase;
/**
*
* @author CHH
* @since 2013-01-19
*/
public class CalculatorTest extends TestCase {

Calculator cal;

//在“每个”测试方法执行之前被调用
public void setUp()
{
//这段代码在这写比较方便,只写一次就够,
//不用在每个方法里写,因为这个方法每次都被调用,生成不同的对象,供测试方法使用
cal = new Calculator();
}

//在“每个”测试方法执行之后被调用
public void tearDown()
{

}

//测试方法:方法名要以test为开头,无参数,无返回类型
public void testAdd()
{
//Calculator cal = new Calculator();
int result = cal.add(1, 2);
//第一个参数是预期的,第二个参数是真实的

Assert.assertEquals(3, result);

//Assert.fail();

}

public void testSubtract()
{
//Calculator cal = new Calculator();
int result = cal.subtract(1, 2);
//第一个参数是预期的,第二个参数是真实的
Assert.assertEquals(-1, result);

}

public void testMultiply()
{
//Calculator cal = new Calculator();
int result = cal.multiply(1, 2);
//第一个参数是预期的,第二个参数是真实的
Assert.assertEquals(2, result);

}

public void testDivide()
{
int result = 0;
//Calculator cal = new Calculator();
try
{
result = cal.divide(4, 2);

}
catch(Exception e)
{
e.printStackTrace();
//让测试失败
Assert.fail();
}
//第一个参数是预期的,第二个参数是真实的
Assert.assertEquals(2, result);

}

//除数为0的情况
public void testDivideByZero()
{
Throwable th = null ;

//Calculator cal = new Calculator();
try
{
cal.divide(1, 0);
Assert.fail();
}
catch(Exception e)
{
th = e ;
//e.printStackTrace();
}

//th 不为空 null
Assert.assertNotNull(th);
//第一个参数是预期的,第二个参数是真实的
Assert.assertEquals(Exception.class, th.getClass());
Assert.assertEquals("除数不能为0", th.getMessage());

}

//加了这个main方法,可以直接以 Java Application 方式运行 ,也可以以 JUnit Test 运行
public static void main(String[] args)
{
//命令行形式打印
junit.textui.TestRunner.run(CalculatorTest.class);

//awt 界面方式显示
//junit.awtui.TestRunner.run(CalculatorTest.class);

//swing 界面方式显示
//junit.swingui.TestRunner.run(CalculatorTest.class);
}

}

 

     从上面的代码中可以看出Junit测试类是通过继承一个TestCase类来实现方法的测试,而这就是Junit4.0以前的测试方式,而在4.0之后他们的实现方式又有了稍微的变化。

Junit4.0之后不再是通过继承TestCase的方式来实现方法的实测,而是采用注解的方式进行的。根据Java 5.0中的新特征(注解,静态导入等),Junit开发团队也随之靠拢,采用注解的方式来进行方法的测试。这样下来相比而言JUnit 4更简单、更丰富和更易于使用。

        Junit4.0测试类

package com.junit4_0;

import static org.junit.Assert.assertEquals;

import org.junit.After;
import org.junit.Before;
import org.junit.Ignore;
import org.junit.Test;
/**
* Junit4.0
* @author CHH
* @since 2013-01-19 晚上10:12
*
*/
public class CalculatorTest {

private static Calculator calculator = new Calculator();

//每个方法测试前调用
@Before
public void clearCalculator() {
calculator.clear();
}

//每个方法测试完以后调用
@After
public void tearDown()
{

}

//@Test:测试方法,表明这是一个测试方法。在Junit中将会自动被执行。
@Test
public void add() {
calculator.add(1);
calculator.add(1);
//第一个参数是预期的,第二个参数是真实的
assertEquals(calculator.getResult(), 2);
}

@Test
public void subtract() {
calculator.add(10);
calculator.substract(2);
//第一个参数是预期的,第二个参数是真实的
assertEquals(calculator.getResult(), 8);
}

//给测试函数设定一个执行时间,超过了这个时间(400毫秒),它们就会被系统强行终止
@Test(timeout=400)
public void divide() {
calculator.add(8);
calculator.divide(2);
//第一个参数是预期的,第二个参数是真实的
assert calculator.getResult() == 5;
}

//使用注释来声明该异常是预期的,异常测试是Junit4中的最大改进
@Test(expected = ArithmeticException.class)
public void divideByZero() {
calculator.divide(0);
}

//@Ignore:忽略的测试方法,标注的含义就是“某些方法尚未完成,暂不参与此次测试”
@Ignore("not ready yet")
@Test
public void multiply() {
calculator.add(10);
calculator.multiply(10);
//第一个参数是预期的,第二个参数是真实的
assertEquals(calculator.getResult(), 100);
}

}

 

  Junit4出了采用的注解的方式来进行测试方法之外,还增加了一些新的元素。

     A、JUnit4添加了两个比较数组的assert() 方法:

  public static void assertEquals(Object[] expected, Object[] actual)

  public static void assertEquals(String message, Object[] expected, Object[] actual)

 

  Junit4常用注解:

    @Test  测试方法,表明这是一个测试方法。在Junit中将会自动被执行。

    @Test(timeOut=400)  给测试函数设定一个执行时间,超过了这个时间(400毫秒),它们就会被系统强行终止

    @Test(expected = ArithmeticException.class)  使用注释来声明该异常是预期的,异常测试是Junit4中的最大改进

    @Ignore("not ready yet")    忽略的测试方法,标注的含义就是“某些方法尚未完成,暂不参与此次测试”

    @Before   每个方法测试前调用

    @After   每个方法测试完以后调用

    @BeforeClass   每个类运行前调用,并且只调用一次

    @AfterClass  每个类运行后调用,并且只调用一次

  

  表格.@BeforeClass/@AfterClass比较于@Before/@After。

@BeforeClass和@AfterClass @Before和@After
在每个类中只有一个方法能被注解。 多个方法能被注解,但其执行的顺序未特别指定,且不运行重载方法。
方法名是不相关的 方法名是不相关的
每个类运行一次 在每个测试方法运行前或运行后运行
在当前类的@BeforeClass方法运行前先运行超类的@BeforeClass方法。在超类中声明的@AfterClass方法将在所有当前类的该方法运行后才运行。 超类中的@Before在所有子类的该方法运行前运行。在超类中的@After在在所有子类的该方法运行后才运行。
必须是公共和非静态的。 必须是公共和非静态的。
即使一个@BeforeClass方法抛出一个异常,所有的@AfterClass方法也保证被运行。 即使一个@Before或者@Test方法抛出一个异常,所有的@After方法也保证被运行。

 

  总结:这两个版本最大的区别在JUnit3.x中测试必须继承 TestCase,并且每个方法名必须以test开头。比如:testMethod1()而在JUnit4.x中不必继承TestCase,采用了注解的 方式。只要在测试的方法上加上注解@Test即可,从而不必再遵循以前的一些显式约定和反射定位测试;在JUnit4.x中如果继承了TestCase, 注解就不起作用了。并且有很重要的一点就是在JUnit4.x中继承了TestCase后,在OutLine视图中测试单个方法时,结果整个类都run 了。还有一点就是,在3.x中需要实现setUp和tearDown方法,而在4.x中无需这样,可以自定义需要在测试前和测试后的方法,在方法前加上 @before,@after就可以了。所以在JUnit4.x不必继承TestCase用注解即可对单个方法进行测试。

 

 

  

 

         

       

本文链接

相关 [java 单元测试 junit] 推荐:

Java 单元测试利器之 Junit

- - 博客园_首页
          因为工作和学习的需要,在代码中查错的时候,第一步就是想知道这个错误具体发生在一个位置,进行一个准确的定位. 而这个定位的工作交给谁来做了呢. 不难猜出也就是这篇博客的主题---Junit. junit是一个开源的框架,也是java这一块的测试工具之一. 想了解详细请上官网,下面用代码来跟大家解释.

项目中单元测试容易出现的普遍问题归纳(Junit/Spring/Spring-test/Dubbo/RocketMQ/JAVA)

- - 编程语言 - ITeye博客
   最近公司要求项目在使用maven构建的时候不能跳过test的生命周期,也就是通过mvn test命令需要将整个项目运行起来. 因为之前项目组的成员都是在eclipse中去执行的unit test,在maven对所有模块构建的都是直接-Dmaven.test.skip=true的方式直接跳过UT的.

Spring与junit测试

- - CSDN博客Web前端推荐文章
1.我们知道无论在J2SE还是android中都有junit测试,利用junit能够帮助方便测试代码. 在之前的博客中我也写了一些J2SE的一些junit测试例子,今天对于Spring中junit小小的讨论一下. 这个Spring测试需要的jar包:. 2.Spring和Junit的关系图. 左边的采用传统的方式,即一般的J2SE的方式测试代码,这种情况会有些问题:.

JUnit学习总结——断言

- - Taobao QA Team
JUnit是Java语言的测试框架,用于编写和运行可重复的测试. 为了便于确定某些被测试函数是否工作正常,JUnit提供了一些辅助函数,这些函数统称为断言. 最近学习JUnit,特将全部JUnit断言整理了一下,方便自己回顾也算是为以后的新人提供一些参考. assertTrue验证condition是否为true.

Android单元测试

- - CSDN博客推荐文章
    单元测试不管对于初学编程还是已经工作了很久的开发者来说,都不乐意花时间去写认为没用的代码进行测试,只要交给测试人员就行了,虽然这样也能把软件改出来,但也许你要花上几倍的时间去修改问题,如果在开发的过程中花点时间去写单元测试代码,把尽可能出问题的地方都测试一遍,把问题扼杀在最开始的地方,这样你就不必为后来找问题出处而烦恼.

Hadoop之MapReduce单元测试

- - ITeye博客
通常情况下,我们需要用小数据集来单元测试我们写好的map函数和reduce函数. 而一般我们可以使用Mockito框架来模拟OutputCollector对象(Hadoop版本号小于0.20.0)和Context对象(大于等于0.20.0). 下面是一个简单的WordCount例子:(使用的是新API).

“单元测试要做多细?”

- - 酷壳 - CoolShell.cn
这篇文章主要来源是StackOverflow上的一个回答——“ How deep are your unit tests?”. 一个有13.8K的分的人( John Nolan)问了个关于TDD的问题,他说——. “TDD需要花时间写测试,而我们一般多少会写一些代码,而第一个测试是测试我的构造函数有没有把这个类的变量都设置对了,这会不会太过分了.

文章: Android中的单元测试

- - InfoQ cn
随着Agile的普及,以及开发人员对测试重要性的认识逐步加深,单元测试已经成了越来越多软件项目开发中不可缺少的一部分. 无论项目是不是采用TDD的形式来进行开发,单元测试都能够为项目的修改和重构提供一定的保障. 有奖参与:天翼伦敦会,上传应用,为中国队加油. QClub七月技术沙龙(太原/北京/上海/厦门/西安 7月21/28/29日 免费报名中.

迈出单元测试的第一步

- - 酷勤网-挖经验 [expanded by feedex.net]
单元测试不仅是软件行业的最佳实践,在敏捷方法的推动下,它也成为了可持续软件生产的支柱. 年度敏捷调查,70%的参与者会对他们的代码进行单元测试. 单元测试和其他敏捷实践密切相关,所以开始编写测试是组织向敏捷转型的踏脚石. 我将在本文介绍符合要求的小技巧,以及在开发周期里进行单元测试的步骤. 没有自动化,单元测试的习惯也不会持续太久.

iOS开发进阶之单元测试

- - 博客园_首页
本文侧重讲述如何在iOS程序的开发过程中使用单元测试. 使用Xcode自带的OCUnit作为测试框架. 单元测试作为敏捷开发实践的组成之一,其目的是提高软件开发的效率,维持代码的健康性. 其目标是证明软件能够正常运行,而不是发现bug(发现bug这一目的与开发成本是正相关的,虽然发现bug是保证软件质量的一种手段,但是很显然这与降低软件开发成本这一目的背道而驰).