JUnit单元测试教程(翻译自Java Code Geeks)

JUnit单元测试教程——终极指南

  • JUnit单元测试教程终极指南

    • 说明
    • 单元测试简介
      • 1 什么是单元测试
      • 2 测试覆盖
      • 3 Java中的单元测试
    • JUnit简介
      • 1 使用Eclipse实现简单JUnit测试例子
    • 使用Eclipse实现完整的JUnit例子
      • 1 创建工程
      • 2 创建要被测试的Java类
      • 3 创建并运行JUnit测试用例
      • 4 使用Ignore注解
      • 5 创建测试套件suite tests
      • 6 创建参数化测试parameterized tests
      • 7 规则Rules
      • 8 策略Categories
    • 命令行运行JUnit测试

说明

本教程翻译自Java Code Geeks,原文网址:https://www.javacodegeeks.com/2014/11/junit-tutorial-unit-testing.html#suite_tests。翻译的过程中,有少部分内容是译者添加的解释说明和对原文章中错误地方的修正。水平有限,如果有错误的地方,希望能在我的博客里告诉我,谢谢。

相关的例子不想自己写的同学们可以去这里下载:http://download.csdn.net/detail/rainnnbow/9603847

1. 单元测试简介

1.1 什么是单元测试?

一个单元可以是一个方法、一个类、一个包、 或者一个子系统。所以术语单元测试表示对代码中的很小的单元的测试行为,以确保它们能够按预期工作。例如,我们给定一些输入,测试是否是预期的输出,或者测试一个条件是真还是假。

这种测试行为能帮助开发者发现隐藏在代码后面的错误,并提高代码质量。单元测试也被用来确保代码能够按照预期工作,以防止未来可能的变化。

1.2 测试覆盖

总的来说,开发者社区对代码测试要达到多少比例存在不同的观点。许多开发者认为代码的测试覆盖率要达到100%。另一些则认为50%或者更低就可以了。但无论如何,你都应该为你的代码中复杂的以及重要的部分编写测试。

1.3 Java中的单元测试

Java中最著名的测试框架是JUnit,本指南是专门介绍JUnit的,接下来的部分将详细介绍该测试框架的更多细节。Java中另一个著名的测试框架是TestNG。

2. JUnit简介

JUnit是一个开源的测试框架,它被用来编写和运行可重复的自动化测试,保证我们的代码按照预期的执行。JUnit被广泛使用:它可以在Java程序中单独使用(使用命令行)或者结合IDE使用,如Eclipse。

JUnit提供以下功能:

  • 断言测试的预期结果。
  • 共享测试数据的特性。
  • 使用Test suites简化测试用例的组织和运行。
  • 图形化和文本化测试用例?(Graphical and textual test runners.)

JUnit可以用来测试以下内容:

  • 一个对象
  • 部分对象——一个方法或几个相互影响的方法
  • 多个对象之间的交互

2.1 使用Eclipse实现简单JUnit测试例子

在这一节我们将展示一个简单的JUnit例子。首先来看一下我们要测试的类:

Calculate.java:

package com.javacodegeeks.junit;

public class Calculate {

    public int sum(int var1, int var2) {
        System.out.println("Adding values: " + var1 + " + " + var2);
        return var1 + var2;
    }

}

在上面的源码中,我们看到该类有一个public的方法sum(),方法接受两个int参数,相加之后返回结果。我们将测试这个方法。因此我们需要创建另一个类,并在这个类中为测试Calculate类中的所有需要测试的方法一一编写测试方法(在这个例子中,我们只有一个方法需要测试)。这是最普通的使用方法。当然如果一个方法非常复杂,我们可以为这个方法编写多个测试方法。编写测试用例的更多细节,我们将在下一节介绍。下面的CalculateTest.java类就是我们的测试类:

package com.javacodegeeks.junit;

import static org.junit.Assert.*;

import org.junit.Test;

public class CalculateTest {

    Calculate calculation = new Calculate();
    int sum = calculation.sum(2, 5);
    int testSum = 7;

    @Test
    public void testSum() {
        System.out.println("@Test sum(): " + sum + " = " + testSum);
        assertEquals(sum, testSum);
    }

}

让我们来解释一下上面的代码。首先我们看到在testSum()方法上有一个@Test注解。这个注解表示这个方法可以作为一个测试用例运行。所以testSum()方法被用来测试sum()方法。我们还看到了assertEquals(sum, testSum)方法,assertEquals ([String message], object expected, object actual)方法用来接手两个对象,并断言这两个对象是否相等。

运行该测试类,Run As–>JUnit Test,程序输出将如下所示:

为了查看JUnit测试的实际结果,Eclipse提供了JUnit窗口来显示测试结果。在这个用例中,测试成功,JUnit窗口不会显示任何错误或失败信息,所以我们看到了如下所示的界面:

如果我们改变一下代码:

int testSum = 10;

修改代码后两个整数的测试不再相等,程序输出将如下所示:

同时,在JUnit窗口中会显示测试出错,并给出错误信息:

2.2 JUnit注解

本节我们将介绍JUnit4支持的基本注解,下表是对这些索引的总结:

让我们来看一个包含了以上注解的测试类的例子:

AnnotationsTest.java:

package com.javacodegeeks.junit;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;

import java.util.ArrayList;

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 AnnotationsTest {

    private ArrayList testList;

    /**
     * if the method isn‘t static, throw following exception:
     * java.lang.Exception: Method onceExecutedBeforeAll() should be static
     */
    @BeforeClass
    public static void onceExecutedBeforeAll() {
        System.out.println("@BeforeClass: onceExecutedBeforeAll");
    }

    @Before
    public void executedBeforeEach() {
        testList = new ArrayList();
        System.out.println("@Before: executedBeforeEach");
    }

    /**
     * If the method isn‘t static, throw following exception:
     * java.lang.Exception: Method onceExecutedAfterAll() should be static
     */
    @AfterClass
    public static void onceExecutedAfterAll() {
        System.out.println("@AfterClass: onceExecutedAfterAll");
    }

    @After
    public void executedAfterEach() {
        testList.clear();
        System.out.println("@After: executedAfterEach");
    }

    @Test
    public void EmptyCollection() {
        assertTrue(testList.isEmpty());
        System.out.println("@Test: EmptyArrayList");
    }

    @Test
    public void OneItemCollection() {
        testList.add("oneItem");
        assertEquals(1, testList.size());
        System.out.println("@Test: OneItemArrayList");
    }

    @Ignore
    public void executionIgnored() {
        System.out.println("@Ignore: This execution is ignored");
    }
}

执行以上测试,控制台输出如下所示:

JUnit窗口显示如下信息:

2.3 Junit断言

本节我们将展示一些断言方法。所有这些方法由Assert类提供,Assert类继承自java.lang.Object。这些断言能帮助你编写测试用例,监测到失败的测试。下表是对一些最常用的断言方法的详细介绍:

让我们看一个上述断言的例子:

AssertionsTest.java

package com.javacodegeeks.junit;

import static org.junit.Assert.*;

import org.junit.Test;

public class AssertionsTest {

    @Test
    public void test() {

        String obj1 = "junit";
        String obj2 = "junit";
        String obj3 = "test";
        String obj4 = "test";
        String obj5 = null;
        int var1 = 1;
        int var2 = 2;
        int[] arithmetic1 = {1,2,3};
        int[] arithmetic2 = {1,2,3};

        assertEquals(obj1, obj2);
        assertSame(obj3, obj4);
        assertNotSame(obj2, obj4);
        assertNotNull(obj1);
        assertNull(obj5);
        assertTrue(var1 != var2);
        assertFalse(var1 == var2);
        assertArrayEquals(arithmetic1, arithmetic2);

    }

}

从以上类中我们可以看到断言方法是怎样工作的。

  • assertEquals():如果两个对象相等,方法正常返回;否则在JUnit窗口中将显示错误,该测试将被中断。
  • assertSame()与assertNotSame():测试两个对象的引用是否指向了同一个对象。
  • assertNull()与assertNotNull():测试一个变量是否是null或非null。
  • assertTrue()与assertFalse():测试一个条件或变量时true或false.。
  • assertArrayEquals():比较两个数组是否相等。如果相等,方法正常返回;否则在JUnit窗口中将显示错误,该测试将被中断。

3. 使用Eclipse实现完整的JUnit例子

本节我们将展示一个使用JUnit的完整例子。我们将讲解怎样创建和运行测试用例,以及怎样使用JUnit的注解和断言。

3.1 创建工程

创建一个名为JUnitGuide的java工程。创建一个包com.javacodegeeks.junit用来放被测试的类。对于测试类,一个好的实践是创建一个专用于测试的源码包。这样被测试类和测试类就被分在了不同的源码包中。创建test包:右键单击你的工程, New–>Source Folder,命名源码包为test。

提示:创建源码包的另一种方式:右键单击你的工程?Properties?Java Build Path,选择Source 项,然后Add Folder?Create New Folder。输入源码包名,点击finish。

你能看到在工程里有两个源码包:

你可以在test源码包中也创建一个名称为com.javacodegeeks.junit的包,这样你的测试类就不会被放在默认的包中。

3.2 创建要被测试的Java类

右击src源码包,创建一个名为FirstDayAtScholl.java的类。该类的public方法将被测试。

FirstDayAtSchool.java

3.3 创建并运行JUnit测试用例

为已经存在的类FirstDayAtSchool.java创建测试用例:选中FirstDayAtSchool.java类,右击选择New?JUnit Test Case。改变源码包,将测试用例类放在test源码包中。确保选择“JUnit 4 test”选项。

点击“Finish”。如果你的项目classpath下还没有包含JUnit4,将会弹出如下所示的信息让你将JUnit4 Library添加进你的工程中。

(译者注:也可以直接在test源码包中像创建普通类一样创建一个测试用例类。只要该类中的方法用@Test注解标注上,就能引入JUnit框架,并成为测试用例。)

以下就是我们创建的名为FirstDayAtSchoolTest.java的测试用例。

FirstDayAtSchoolTest.java

右键Run As?JUnit Test,运行测试用例。

程序输出如下所示:

JUnit窗口显示如下:

此时JUnit窗口没有任何错误或失败。如果我们改变其中一个数组,让它包含比预期更多的元素:

再次运行测试类,JUnit窗口将显示有一个失败的测试用例:

或者,我们再次改变数组,让它包含与预期不同的元素:

再次运行测试类,JUnit窗口将再次显示一个测试用例fail:

3.4 使用@Ignore注解

在上面的例子中,让我们看看怎样使用@Ignore注解。在测试类FirstDayAtSchoolTest.java的testAddPencils()方法上标注@Ignore注解。通过这种方式,我们将该测试方法忽略掉,测试时不会执行。

执行测试,输出如下所示:@Ignore注解的测试方法没有执行。

JUnit窗口显示如下:

现在,我们去掉testAddPencils()方法上的@Ignore注解,将@Ignore注解标注在FirstDayAtSchoolTest.java类上。

运行该测试类发现:整个测试用例将不会执行,所以控制台上没有任何输出。JUnit窗口显示如下信息:

3.5 创建测试套件(suite tests)

本节,我们将展示如何创建测试套件。测试套件是来自于不同类的多个测试用例的集合。使用@Runwith和@Suite注解可以让这些测试类一起运行。当你有许多测试类并且你希望这些测试类一起执行时,这是非常有用的。

在上一节类的基础上,我们可以创建两个测试类。一个测试prepareMyBag()方法,另一个测试addPencils()方法。两个测试类如下所示:

PrepareMyBagTest.java.

AddPencilsTest.java.

我们来创建一个测试套件类来运行以上两个测试类。测试套件类SuiteTest.java如下所示:

SuiteTest.java.

使用@Suite.SuiteClasses注解来定义哪些测试类将被包含进测试套件一起执行。

运行该测试套件,这两个测试类将按照在@Suite.SuiteClasses注解中声明的顺序执行。

执行完毕后JUnit窗口显示信息如下:

3.6 创建参数化测试(parameterized tests)

本节我们将展示如何创建参数化的测试。我们将使用前面的2.1节中的类作为被测试类。

什么时候一个测试类才能被认为是一个参数化的测试类呢?当测试类满足下列条件的时候:

? 该类使用@RunWith(Parameterized.class)标注;

@RunWith注解告诉JUnit使用该注解标明的执行器执行测试用例,而不是使用JUnit内置的默认执行器。Parameterized是JUnit中的一个执行器,该执行器将使用一组不同的输入来多次执行一个相同的测试用例。

? 该类有唯一的构造函数来创建测试数据;

? 该类有一个static方法用来产生并返回测试数据,该方法使用@Parameters注解标注;

? 该类有一个使用@Test标注的测试用例(译者注:废话吗这不是)。

我们创建了一个新的测试类CalculateTest.java。该类遵循以上的规则。该类源码如下:

上如代码满足以上的所有规则。addedNumbers方法使用@Parameters标注,返回数组的集合。每一个数组包含一次测试执行的I/O数据。数组中元素的个数必须和构造函数中参数的个数一致。在该例子中,一个数组包含三个元素,两个代表要被相加的数,一个代表结果。

运行该测试用例,控制台输出如下所示:

JUnit窗口输出信息如下:

从上述信息可以看出,该测试用例执行了4次,这正是使用@Parameters注解标注的方法中输入的测试数据的个数。

3.7 规则(Rules)

本节我们将介绍JUnit4的一个新特性,叫做规则(Rules)。Rules允许我们灵活的增加或重新定义每一个测试方法的行为。为达到这个目的,使用@Rule注解标注测试类中public的域(fields)。这些域必须是MethodRule类型的,他们标明了一个测试方法的运行或结果报告作出了哪些改变。一个测试方法可以应用多个MethodRule。MethodRule接口有许多实现,如ErrorCollector,该规则允许测试用例在发现第一次错误是可以继续运行;ExpectedException,该规则允许我们明确预期异常的类型及异常信息;TestName,该规则允许我们在测试方法中获取到当前测试方法的名称;等等其他规则。除了JUnit已经定义的规则,开发者也可以自定义规则并在测试用例中使用。

下面,我们展示一个使用已经存在的TestName规则的例子。当一个测试类开始执行时TestName被调用。

NameRuleTest.java

如上所示:@Rule注解标注了一个public的域name,该域是MethodRule类型的。确切的说,该类是MethodRule接口的实现类MethodRule类型。然后我们就可以使用name在我们的测试方法中获取当前正在运行的测试方法的名字了。

(译者注:关于Rules的详细说明,请查看JUnit4官方文档:https://github.com/junit-team/junit4/wiki/Rules。运行里面的例子,有疑问就修改例子测试,一目了然。Rules还是有不少用处的。)

3.8 策略(Categories)

JUnit的另一个新特性是策略,这允许你将特定的测试放在一起形成一个分组(group),并可以包含或排除某些分组。例如你可以将运行慢的测试用例与运行快的测试用例分开。JUnit提供了@Category注解为一个测试用例标明策略。以下是使用该新特性的例子。该特性从JUnit4.8开始支持。

首先,定义两个策略,FastTests和SlowTests。一个策略可以是一个类或者一个借口。

以上的代码中,我们在A类的b()方法上使用了@Category注解,标注该方法在SlowTests策略中。所以,@Category注解不仅可以标注整个类,也可以标注某一个测试方法。

以上的代码中,我们看到整个B类使用了@Category标注。在类上标注后,该类的所有测试方法都会自动包含进@Category中声明的策略中。我们也可以看到,一个类或者一个测试方法可以属于多个策略。

以上代码中,我们看到有一个名为SlowTestSuite_1的测试套件。一般情况下,我们认为策略就是一种测试套件。在该套件中,我们使用@IncludeCategory注解标明哪些策略将会被执行。在该例中,属于SlowTests策略的所有方法将会被执行。因此,A类中的b()方法和B类中的c方法将被执行,他们都属于SlowTests策略。

以上代码中,我们对测试套件做了一些修改,我们添加了一个新的注解@ExcludeCategory,该注解表明那些策略将被排除。在本例中,只有A类的b()方法会执行,因为他是唯一只属于SlowTests策略,并不属于FastTests策略的测试方法。

通过以上两个例子我们看到,A类的a()方法从未执行,因为它不属于任何策略。

5. 命令行运行JUnit测试

通过使用org.junit.runner.JUnitCore 类,可以在Eclipse之外运行测试用例。该类提供了runClasses()方法允许执行一个或多个测试类。runClasses()方法的返回类型是一个org.junit.runner.Result对象。该对象可以搜集所有测试的信息。如果有失败的测试用例,你可以使用org.junit.runner.notification.Failure对象来获取失败的测试用例的描述。

下面的流程展示了如何在Eclipse之外运行你的测试。

创建一个新类JunitRunner.java如下所示:

JunitRunner.java

我们选择运行名为AssertionsTest的测试类。

? 打开DOS窗口,并定位到JunitRunner.java所在的目录(译者注:本人的目录是**\JUnitGuide\test\com\javacodegeeks\junit)。

? 编译测试类和Runner类。

javac -classpath “D:\learnTech\test\junit-4.11.jar”;”D:\learnTech\test\hamcrest-core-1.3.0.jar”; AssertionsTest.java JunitRunner.java

和在Eclipse中一样,我们需要将JUnit的jar包包含进classpath中。运行完上述命令。在Junitrunner.java所在的目录下就生成了AssertionsTest.class 和JunitRunner.class两个class文件。如下所示:

? 在DOS窗口中,退回到test源码目录(译者注:本人的目录是**\JUnitGuide\test)。

? 运行JunitRunner类。

java -classpath “D:\learnTech\test\junit-4.11.jar”;”D:\learnTech\test\hamcrest-core-1.3.0.jar”; JunitRunner

输出结果为:

时间: 2024-10-09 05:05:45

JUnit单元测试教程(翻译自Java Code Geeks)的相关文章

解决Junit单元测试 找不到类 ----指定Java Build Path

做junit 单元测试时,发现怎么执行都是以前编译过得代码. 最后找到原因了, src/test/java 编译完的.class路径是 Default output folder Default output folder:  zphVip/src/main/webapp/WEB-INF/classes   解决 1 勾选 Allow output floders for source folders  ------允许源文件夹编译过后的.class输入文件夹自己指定 2 Edit 指定 out

Java反射学习总结终(使用反射和注解模拟JUnit单元测试框架)

本文是Java反射学习总结系列的最后一篇了,这里贴出之前文章的链接,有兴趣的可以打开看看. http://blog.csdn.net/a396901990/article/category/2302221 本文介绍了如何利用反射和注解去简单的模拟JUnit4单元测试框架,之所以选择JUnit4是因为4.0以后最大的改进就是使用了注解.需要注意的是这里并不是完全的模拟,只是简单实现了一下Runner类和JUnit注解相关的工作流程.所以本文的主要目的是介绍反射和注解的使用.废话不多说,直接进入正文

Eclipse使用Junit单元测试

我们在编写大型程序的时候,需要写成千上万个方法或函数,这些函数的功能可能很强大,但我们在程序中只用到该函数的一小部分功能,并且经过调试可以确定,这一小部分功能是正确的.但是,我们同时应该确保每一个函数都完全正确,因为如果我们今后如果对程序进行扩展,用到了某个函数的其他功能,而这个功能有bug的话,那绝对是一件非常郁闷的事情.所以说,每编写完一个函数之后,都应该对这个函数的方方面面进行测试,这样的测试我们称之为单元测试.传统的编程方式,进行单元测试是一件很麻烦的事情,你要重新写另外一个程序,在该程

Junit 4 Tutorials(Junit 4 教程)

本教程是比较全面的.较新的Junit 4 实用教程,译自:http://www.javatutorials.co.in/junit-4/,希望对大家有所帮助! 以下是本教程的内容设置,读者可以点击以下标题进行阅读: Junit测试框架介绍 Junit 测试框架是最流行的Java单元测试框架.Junit被用来开发Java类的单元测试. Junit Eclipse教程 介绍eclipse IDE 中junit的相关特性及其使用方法.在eclipse IDE中书写和运行单元测试代码的样例. Junit

Junit 4 Tutorials(Junit 4 教程) 一、Junit简介及Junit Eclipse 教程

Junit 测试框架简介 测试框架是最流行的Java单元测试框架.Junit被用来开发对Java类的单元测试.它就是一个类包,提供了各种方法来测试Java类中的方法(method). Junit 4 特性 简单的注解,提供书写Junit测试的基本特性 断言方法(Assert Methods)比较测试的方法执行结果值和期望值 @Ignore 注解,忽略测试方法或者测试类的执行 期望异常测试 超时测试 , 测试方法的执行时间 测试组件,一起运行一些测试类 参数化测试, 以不同的输入参数值测试方法 J

Junit 4 Tutorials(Junit 4 教程) 四、Junit4 参数化测试

Junit 4 参数化测试 允许通过变化范围的参数值来测试方法.参数擦测试可以通过以下简单的步骤实现: 对测试类添加注解 @RunWith(Parameterized.class) 将需要使用变化范围参数值测试的参数定义为私有变量 使用上一步骤声明的私有变量作为入参,创建构造函数 .创建一个使用@Parameters注解的公共静态方法,它将需要测试的各种变量值通过集合的形式返回. 使用定义的私有变量定义测试方法 Junit 4 参数化测试样例 EvenNumberChecker.java 校验输

Qt官方教程翻译——QML Applications

附网址:http://qt-project.org/doc/qt-5/qmlapplications.html QML Applications QML是一种声明式语言,它提供了一组接口用来描述视觉组件以及他们的互动和相关性.它是一个高度可读的语言,并且被设计成使组件以一个动态的方式相互连接.同时它使组件很容易被复用以及创建定制的用户界面.使用QtQuick模块,设计者和开发者可以很容易使用QML建立流体动画的用户界面,并将这些界面连接到后端的C++库上面. What is QML? QML是一

JUnit单元测试

JUnit单元测试: 1.什么是单元测试:我们在完成一个项目后,需要对其代码逻辑进行简单的全方面的测试,看看代码逻辑是否正确,比如,我们写了一片登录的代码,测试时,就要分别用手机号,账号去登录看是否能登上,如果输错密码或账号看是否会报错等,这些都需要我们去测试,测试成功以后就可以上交了.测试是为了以防万一代码会出错,项目上交之前,测试是必不可少的一个环节.测试代码需要[学Java,到凯哥学堂kaige123.com]我们自己写,没有JUnit我们也能测试(在main方法中调用自己写的测试代码即可

spring && Cobertura && maven &&junit 单元测试以及测试覆盖率

1. 目的: junit 单元测试,Cobertura   测试覆盖率报告 项目目录结构 2. maven 配置 <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://mave