测试

Maven Test

Maven本身并不是一个单元测试框架,它只是在构建执行到特定生命周期阶段的时候,通过插件来执行JUnit或者TestNG的测试用例。这个插件就是maven-surefire-plugin,也可以称为测试运行器(Test Runner),它能兼容JUnit 3JUnit 4以及TestNG。在默认情况下,maven-surefire-plugintest目标会自动执行测试源码路径(默认为src/test/java/)下所有符合一组命名模式的测试类。这组模式为:

  • *Test_.java:任何子目录下所有命名以Test开关的Java类。
  • **Test.java:任何子目录下所有命名以Test结尾的Java类。
  • **TestCase.java:任何子目录下所有命名以TestCase结尾的Java类。

Java世界中,由Kent BeckErich Gamma建立的JUnit是事实上的单元测试标准。要使用JUnit,我们首先需要为Hello World项目添加一个JUnit依赖,修改项目的POM如代码清单。

<?xml version="1.0" encoding="UTF-8"?>
<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://maven.apache.org/maven-v4_0_0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>com.juvenxu.mvnbook</groupId>
  <artifactId>hello-world</artifactId>
  <version>1.0-SNAPSHOT</version>
  <name>Maven Hello World Project</name>
  <dependencies>
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>4.7</version>
      <scope>test</scope>
    </dependency>
  </dependencies>
</project>

代码中添加了dependencies元素,该元素下可以包含多个dependency元素以声明项目的依赖,这里我们添加了一个依赖——groupIdjunitartifactIdjunitversion4.7。前面我们提到groupIdartifactIdversion是任何一个Maven项目最基本的坐标,JUnit也不例外,有了这段声明,Maven就能够自动下载junit-4.7.jar。也许你会问,Maven从哪里下载这个jar呢?在Maven之前,我们可以去JUnit的官网下载分发包。而现在有了Maven,它会自动访问中央仓库(http://repo1.maven.org/maven2/) ,下载需要的文件。读者也可以自己访问该仓库,打开路径junit/junit/4.7/,就能看到junit-4.7.pomjunit-4.7.jar

上述POM代码中还有一个值为test的元素scopescope为依赖范围,若依赖范围为test则表示该依赖只对测试有效,换句话说,测试代码中的import JUnit代码是没有问题的,但是如果我们在主代码中用import JUnit代码,就会造成编译错误。如果不声明依赖范围,那么默认值就是compile,表示该依赖对主代码和测试代码都有效。

配置了测试依赖,接着就可以编写测试类,回顾一下前面的HelloWorld类,现在我们要测试该类的sayHello()方法,检查其返回值是否为“Hello Maven”。在src/test/java目录下创建文件,其内容如代码清单如下:

public class HelloWorldTest {

  @Test
  public void testSayHello() {
    HelloWorld helloWorld = new HelloWorld();

    String result = helloWorld.sayHello();

    assertEquals("Hello Maven", result);
  }
}

测试用例编写完毕之后就可以调用Maven执行测试,运行mvn clean test。构建在执行compiler:testCompile任务的时候失败了,Maven输出提示我们需要使用-source 5或更高版本以启动注释,也就是代码中JUnit 4@Test注解。这是Maven初学者常常会遇到的一个问题。由于历史原因,Maven的核心插件之一compiler插件默认只支持编译Java 1.3,因此我们需要配置该插件使其支持Java 5,见代码清单:

<project>
<build>
<plugins>
  <plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-compiler-plugin</artifactId>
    <configuration>
       <source>1.5</source>
       <target>1.5</target>
     </configuration>
   </plugin>
</plugins>
</build>
</project>

POM省略了除插件配置以外的其他部分。现在再执行mvn clean test,结果正常。

测试命令

Maven中使用packageinstall等命令时会自动调用Test组件,mvn package -DskipTests命令可以跳过测试。也可以在插件配置的时候设置跳过:

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-surefire-plugin</artifactId>
    <version>2.5</version>
    <configuration>
        <skipTests>true</skipTests>
    </configuration>
</plugin>

maven-surefire-plugin提供了一个test参数让Maven用户能够在命令行指定要运行的测试用例。如:

mvn test -Dtest=RandomGeneratorTest

也可以使用通配符:

mvn test -Dtest=Random*Test

或者也可以使用“”号指定多个测试类:

mvn test -Dtest=Random*Test,AccountCaptchaServiceTest

如果由于历史原因,测试类不符合默认的三种命名模式,可以通过pom.xml设置maven-surefire-plugin插件添加命名模式或排除一些命名模式。

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-surefire-plugin</artifactId>
    <version>2.5</version>
    <configuration>
        <includes>
            <include>**/*Tests.java</include>
        </includes>
        <excludes>
            <exclude>**/*ServiceTest.java</exclude>
            <exclude>**/TempDaoTest.java</exclude>
        </excludes>
    </configuration>
</plugin>

Coverage |测试覆盖率

maven-surefire-plugin

如果你执行过mvn test或者执行其他maven命令时跑了测试用例,你就已经用过maven-surefire-plugin了。maven-surefire-pluginmaven里执行测试用例的插件,不显示配置就会用默认配置。这个插件的surefire:test命令会默认绑定maven执行的test阶段。

配置JUnit

插件自动匹配

最简单的配置方式就不配置或者是只声明插件。

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-surefire-plugin</artifactId>
    <version>2.19</version>
</plugin>

这个时候maven-surefire-plugin会按照如下逻辑去寻找JUnit的版本并执行测试用例。

if the JUnit version in the project >= 4.7 and the parallel attribute has ANY value
    use junit47 provider
if JUnit >= 4.0 is present
    use junit4 provider
else
    use junit3.8.1

插件手动匹配

当然,如果你明确用的是JUnit4.7及以上版本,可以明确声明:

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-surefire-plugin</artifactId>
    <version>2.19</version>
    <dependencies>
        <dependency>
            <groupId>org.apache.maven.surefire</groupId>
            <artifactId>surefire-junit47</artifactId>
            <version>2.19</version>
        </dependency>
    </dependencies>
</plugin>

JUnit4.0()JUnit4.7(不含)的版本,这样声明:

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-surefire-plugin</artifactId>
    <version>2.19</version>
    <dependencies>
        <dependency>
            <groupId>org.apache.maven.surefire</groupId>
            <artifactId>surefire-junit4</artifactId>
            <version>2.19</version>
        </dependency>
    </dependencies>
</plugin>

JUnit3.8()JUnit4.0(不含)的版本,这样声明:

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-surefire-plugin</artifactId>
    <version>2.19</version>
    <dependencies>
        <dependency>
            <groupId>org.apache.maven.surefire</groupId>
            <artifactId>surefire-junit3</artifactId>
            <version>2.19</version>
        </dependency>
    </dependencies>
</plugin>

JUnit3.8以下的版本surefire不支持。建议大家用最新的JUnit版本,目前是4.12.

<dependencies>
    [...]
    <dependency>
        <groupId>junit</groupId>
        <artifactId>junit</artifactId>
        <version>4.12</version>
        <scope>test</scope>
    </dependency>
    [...]
</dependencies>
下一页