JUnit学习笔记
JUnit框架
JUnit是一个测试框架,它使用注释来标识指定测试的方法。JUnit是Github上托管的一个开源项目。
如何在JUnit中定义测试?
- JUnit 测试是类中包含的方法,仅用于测试。这称为测试类。
- 要定义某种方法为测试方法,请使用注释对其进行
@Test
注释。此方法执行被测代码。 - 您可以使用JUnit或另一个assert框架提供的assert方法来检查预期结果与实际结果。这些方法调用通常称为断言或断言语句。
JUnit测试示例
以下代码显示了使用JUnit 5
版本的JUnit
测试。该测试假定MyClass
该类存在并具有一个multiply(int, int)
方法。
import static org.junit.jupiter.api.Assertions.assertEquals;
import org.junit.jupiter.api.Test;
public class MyTests {
@Test
public void multiplicationOfZeroIntegersShouldReturnZero() {
MyClass tester = new MyClass(); // MyClass is tested
// assert statements
assertEquals(0, tester.multiply(10, 0), "10 x 0 must be 0");
assertEquals(0, tester.multiply(0, 10), "0 x 10 must be 0");
assertEquals(0, tester.multiply(0, 0), "0 x 0 must be 0");
}
}
JUnit命名约定
- JUnit测试有几种潜在的命名约定。对于类的一种广泛使用的解决方案是在测试类名称的末尾使用
Test
后缀。 - 通常,测试名称应说明测试的用途。如果正确完成,可以避免阅读实际的实现。
- 如果使用的是Maven构建系统,则应将
Test
后缀用于测试类。Maven构建系统(通过其surfire插件)会在其测试范围内自动包括此类。
测试执行顺序
- JUnit假定所有测试方法都可以按任意顺序执行。编写良好的测试代码不应假定任何顺序,即测试不应依赖于其他测试。
- 从JUnit 4.11开始,默认设置是使用确定性但不可预测的顺序来执行测试。
使用JUnit 4
定义测试方法
JUnit使用注释将方法标记为测试方法并进行配置。下表概述了4.x和5.x版本的JUnit中最重要的注释。所有这些注释都可以在方法上使用。
断言
JUnit通过Assert类提供了静态方法来测试某些条件。这些assert语句通常以开头assert。它们使您可以指定错误消息,预期结果和实际结果。一个断言方法比较通过测试返回预期值实际值。
JUnit测试套件
如果您有多个测试类,则可以将它们组合成一个测试套件。运行测试套件将以指定顺序执行该套件中的所有测试类。一个测试套件也可以包含其他测试套件。
以下示例代码演示了测试套件的用法。它包含两个测试类MyClassTest
和MySecondClassTest
。如果要添加另一个测试类,可以将其添加到@Suite.SuiteClasses
语句中。
package com.vogella.junit.first;
import org.junit.runner.RunWith;
import org.junit.runners.Suite;
import org.junit.runners.Suite.SuiteClasses;
@RunWith(Suite.class)
@SuiteClasses({
MyClassTest.class,
MySecondClassTest.class })
public class AllTests {
}
禁用测试
@Ignore
批注允许静态忽略测试。或者,您可以使用Assume.assumeFalse
或Assume.assumeTrue
定义测试条件。 Assume.assumeFalse
如果条件评估为true
,则将测试标记为无效。 Assume.assumeTrue
如果条件为假,则将测试评估为无效。
例如,以下内容禁用了Linux
上的测试:
`Assume.assumeFalse(System.getProperty("os.name").contains("Linux"));`
参数化测试
JUnit
允许您在测试类中使用参数。此类可以包含一个测试方法,并且使用提供的不同参数来执行此方法。
您可以使用@RunWith(Parameterized.class)
注释将测试类标记为参数化测试。
这样的测试类必须包含带有注释的静态方法@Parameters
该方法生成并返回数组的集合。此集合中的每个项目都用作测试方法的参数。
您可以@Parameter
在公共字段上使用批注获取在测试中注入的测试值。
以下代码显示了参数化测试的示例。为此示例,它测试了作为内部类包括在内的类的multiply()方法MyClass。
package testing;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import org.junit.runners.Parameterized.Parameters;
import java.util.Arrays;
import java.util.Collection;
import static org.junit.Assert.assertEquals;
import static org.junit.runners.Parameterized.*;
@RunWith(Parameterized.class)
public class ParameterizedTestFields {
// fields used together with @Parameter must be public
@Parameter(0)
public int m1;
@Parameter(1)
public int m2;
@Parameter(2)
public int result;
// creates the test data
@Parameters
public static Collection<Object[]> data() {
Object[][] data = new Object[][] { { 1 , 2, 2 }, { 5, 3, 15 }, { 121, 4, 484 } };
return Arrays.asList(data);
}
@Test
public void testMultiplyException() {
MyClass tester = new MyClass();
assertEquals("Result", result, tester.multiply(m1, m2));
}
// class to be tested
class MyClass {
public int multiply(int i, int j) {
return i *j;
}
}
}
除了使用@Parameter
注释之外,您还可以使用构造函数,在该构造函数中存储每个测试的值。用注释的方法提供的每个数组中的元素数 @Parameters
必须与类的构造函数中的参数数相对应。将为每个参数创建该类,并将测试值通过构造函数传递给该类。
package de.vogella.junit.first;
import static org.junit.Assert.assertEquals;
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 ParameterizedTestUsingConstructor {
private int m1;
private int m2;
public ParameterizedTestUsingConstructor(int p1, int p2) {
m1 = p1;
m2 = p2;
}
// creates the test data
@Parameters
public static Collection<Object[]> data() {
Object[][] data = new Object[][] { { 1 , 2 }, { 5, 3 }, { 121, 4 } };
return Arrays.asList(data);
}
@Test
public void testMultiplyException() {
MyClass tester = new MyClass();
assertEquals("Result", m1 * m2, tester.multiply(m1, m2));
}
// class to be tested
class MyClass {
public int multiply(int i, int j) {
return i *j;
}
}
}
如果运行此测试类,则将使用每个定义的参数执行测试方法。在上面的示例中,测试方法执行了3次。
JUnit5概述
JUnit 5由许多离散组件组成:
- JUnit平台-基础层,可在JVM上启动不同的测试框架
- Junit Jupiter-是由JUnit Platform启动的JUnit 5测试框架
- JUnit Vintage-运行较早测试的传统TestEngine
将JUnit 5与Maven结合使用
本示例说明如何将JUnit 5的所有组件导入项目。
我们需要向Maven surefire注册各个组件:
<build>
<plugins>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.1</version>
<configuration>
<source>${java.version}</source>
<target>${java.version}</target>
</configuration>
</plugin>
<plugin>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.19.1</version>
<configuration>
<includes>
<include>**/Test*.java</include>
<include>**/*Test.java</include>
<include>**/*Tests.java</include>
<include>**/*TestCase.java</include>
</includes>
<properties>
<!-- <includeTags>fast</includeTags> -->
<excludeTags>slow</excludeTags>
</properties>
</configuration>
<dependencies>
<dependency>
<groupId>org.junit.platform</groupId>
<artifactId>junit-platform-surefire-provider</artifactId>
<version>${junit.platform.version}</version>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-engine</artifactId>
<version>${junit.jupiter.version}</version>
</dependency>
<dependency>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
<version>${junit.vintage.version}</version>
</dependency>
</dependencies>
</plugin>
</plugins>
</build>
并添加依赖项:
<dependencies>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-api</artifactId>
<version>${junit.jupiter.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>${junit.version}</version>
<scope>test</scope>
</dependency>
</dependencies>
定义测试方法
JUnit
使用注释将方法标记为测试方法并进行配置。下表概述了4.x和5.x版本的JUnit
中最重要的注释。所有这些注释都可以在方法上使用。
禁用测试
该@Disabled
注释允许静态地忽略测试。
或者,您可以使用Assumptions.assumeFalse
或Assumptions.assumeTrue
定义测试停用的条件。 Assumptions.assumeFalse
如果条件评估为true
,则将测试标记为无效。Assumptions.assumeTrue
如果条件为假,则将测试评估为无效。例如,以下内容禁用了Linux
上的测试:
Assumptions.assumeFalse(System.getProperty("os.name").contains("Linux"));
测试套件
要一起运行多个测试,可以使用测试套件。它们允许聚合多个测试类。JUnit 5提供了两个注释:
- @SelectPackages -用于指定测试套件的软件包名称
- @SelectClasses-用于指定测试套件的类。它们可以位于不同的程序包中。
示例:
@RunWith(JUnitPlatform.class)
@SelectPackages("com.vogella.junit5.examples")
public class AllTests {}
@RunWith(JUnitPlatform.class)
@SelectClasses({AssertionTest.class, AssumptionTest.class, ExceptionTest.class})
public class AllTests {}