草庐IT

Maven知识点-插件-maven-surefire-plugin简介

Hello姜先森 2023-09-28 原文

Maven本身并不是一个单元测试框架,Java 世界中主流的单元测试框架为JUnit 和TestNG。

Maven 所做的只是在构建执行到特定生命周期阶段的时候,通过插件来执行JUnit或者TestNG的测试用例。

这一插件就是maven-surefire-plugin,可以称之为测试运行器(Test Runner),它能很好地兼容JUnit 3JUnit4以及TestNG。

如果你懂的Maven的生命周期(不熟悉可以先看一下这里->Maven生命周期),那你应该知道生命周期阶段test被定义为“使用单元测试框架运行测试”。我们知道Maven生命周期阶段需要绑定到某个具体插件的目标才能完成真正的工作,test阶段就是和maven-surefire-plugin的test目标绑定了,这是Maven的内置绑定,具体自行百度查看。

在默认情况下,maven-surefire-plugin的test目标会自动执行测试源码路径(默认src/test/java)下所有符合一组命名模式的测试类,这组模式如下:

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

只要将测试类按上述模式命名,Maven 就能自动运行它们,用户也就不再需要定义测试集合 (TestSuite)来聚合测试用例 (TestCase)。关于模式需要注意的是,以 Tests 结尾的测试类是不会得以自动执行的。

当然,为了能够运行测试,Maven 需要在项目中引人Junit测试框架的依赖,这里不再赘述。

1.跳过测试

日常工作中,软件开发人员总有很多理由来跳过单元测试,“我敢保证这次改动不会导致任何测试失败”,“测试运行太耗时了,暂时跳过一下”,“有持续集成服务跑所有测试呢,我本地就不执行啦”。

在大部分情况下,这些想法都是不对的,任何改动都要交给测试去验证,测试运行耗时过长应该考虑优化测试,更不要完全依赖持续集成服务来报告错误测试错误应该尽早在尽小范围内发现,并及时修复。

不管怎样我们总会要求Maven 跳过测试,这很简单在命令行加人参数skipTests就可以了。例如:

mvn clean install -DskipTests

Mave会告诉你它跳过了测试:

当然,也可以在POM中配置maven-surefire-plugin 插件来提供该属性。但这是不推荐的做法,如果配置 POM 让项目长时间地跳过测试,则还要测试代码做什么呢?

 <build>
   <pluginManagement>
     <plugins>
       <plugin>
         <artifactId>maven-surefire-plugin</artifactId>
         <configuration>
            <!-- 跳过测试 -->
           <skip>true</skip>
         </configuration>
       </plugin>
     </plugins>
   </pluginManagement>
 </build>

有的时候,用户不只是仅仅跳过测试运行,还想临时地跳过测试代码的编译,Maven也允许你这么做,但这也是不推荐的!

mvn clean install -Dmaven.test.skip=true


参数”-Dmaven.test.skip=true“控制了maven-compiler-plugin和maven-surefire-plugin两个插件的行为,测试代码的编译跳过了,测试运行也跳过了。

对于maven命令行参数maven.test.skip=true的POM配置如下:

<build>
    <pluginManagement>
      <plugins>
        <plugin>
          <artifactId>maven-compiler-plugin</artifactId>
          <configuration>
            <!-- -Dmaven.test.skip=true 提过测试代码的编译和运行 -->
            <skip>true</skip>
          </configuration>
        </plugin>
        <plugin>
          <artifactId>maven-surefire-plugin</artifactId>
          <configuration>
            <!-- -DskipTests 跳过测试代码的运行 -->
            <skip>true</skip>
          </configuration>
        </plugin>
      </plugins>
    </pluginManagement>
  </build>

两个插件的test目标都是制定了一个skip参数控制测试代码的编译或运行的跳过。

2.动态指定要运行的测试用例

反复运行单个测试用例是日常开发中很常见的行为。例如,项目代码中有一个失败的测试用例,开发人员就会想要再次运行这个测试以获得详细的错误报告,在修复该测试的过程中,开发人员也会反复运行它,以确认修复代码是正确的。如果仅仅为了一个失败的测试用例而反复运行所有测试,未免太浪费时间了,当项目中测试的数目比较大的时候这种浪费尤为明显。

maven-surefire-plugin提供了一个test参数让Maven 用户能够在命令行指定要运行的测试用例。例如,如果只想运行 StringTest测试类(我自己Demo项目中的),就可以使用如下命令:

mvn test -Dtest=StringTest

这里test参数的值是测试用例的类名,这行命令的效果就是只有 StringTest这一个测试类得到运行。

maven-surefire-plugin的test参数还支持高级一些的赋值方式,能让用户更灵活地指定需要运行的测试用例。例如:

mvn test -Dtest=String*Test

星号可以匹配零个或多个字符,上述命令会运行项目中所有类名以String开头、Test结尾的测试类。

除了星号匹配,还可以使用逗号指定多个测试用例:

mvn test -Dtest=StringTest,DoubleTest

该命令的 test参数值是两个测试类名,它们之间用号隔开,其效果就是告诉Maven只运行这两个测试类。

当然,也可以结合使用星号和逗号。例如:

mvn test -Dtest=String*Test,DoubleTest

需要注意的是,上述几种从命令行动态指定测试类的方法都应该只是临时使用,如果长时间只运行项目的某几个测试,那么测试就会慢慢失去其本来的意义。

test参数的值必须匹配一个或者多个测试类,如果maven-surefire-plugin 找不到任何匹配的测试类,就会报错并导致构建失败。例如下面的命令没有匹配任何测试类:

mvn test -Dtest


根据截图红框后面括号中的提示,可以加上参数 -DfailIfNoTests=false,告诉maven-surefire-plugin即使没有任何测试也不要报错

mvn test -Dtest -DfailIfNoTests=false

注意:-DfailIfNoTests=false 是 fail If No Tests,避免l(小写L)和I(大写i)的区别。

这样构建就能成功了。

3.包含与排除测试用例

文章开头说过,maven-surefire-plugin的test目标会自动执行测试源码路径下所有符合一组命名模式的测试类,其实除了Maven约定好的测试类命名规则外,插件还允许用户通过额外的配置来自定义包含一些其他的测试类,或者排除一些符合命名规则的测试类。

例如有的开发人员创建的测试类总是以Tests结尾,默认这是不符合maven-surefire-plugin的测试类命名规则的,因此不会自动执行,但是我们可以自定义让Tests也被Maven自动运行。

 <plugins>
     <plugin>
         <artifactId>maven-surefire-plugin</artifactId>
         <configuration>
             <includes>
                 <!-- 不符合默认命名规则的测试类也被自动运行 -->
                 <include>**/*.Tests.java</include>
             </includes>
         </configuration>
     </plugin>
 </plugins>

**匹配任意路径,*匹配0个或多个字符。

类似的,可以使用<excludes>来配出一些符合默认命名模式的测试类,如下:

 <plugins>
     <plugin>
         <artifactId>maven-surefire-plugin</artifactId>
         <configuration>
             <includes>
                 <!-- 不符合默认命名规则的测试类也被自动运行 -->
                 <include>**/*.Tests.java</include>
             </includes>
             <excludes>
                 <!-- 排除以Test开头的测试类, 排除StringTest类 -->
                 <exclude>**/Test*.java</exclude>
                 <exclude>**/StringTest.java</exclude>
             </excludes>
         </configuration>
     </plugin>
 </plugins>

<excludes>中配置的测试类,maven-surefire-plugin将不再自动运行他们。

4.测试报告

除了命令行的输出,我们还可以使用maven-surefire-plugin等插件以文件的形式生成丰富的测试报告。

默认情况下,maven-surefire-plugin会在target/surefire-reports目录下生成两种格式的错误报告:

  1. 简单的文本格式
  2. 与Junit兼容的XML格式

例如我自己的Demo项目中有一个StringTest测试类,运行了自己的Demo项目后,(取消跳过测试代码的编译和运行)


前者文件内容十分简单

这样的报告其实对于测试信息就足够了,而第二个文件xml的测试报告主要是为了支持工具的解析,例如Eclipse的JUnit插件可以直接打开xml的报告,由于这种xml的格式成为了java单元测试报告的标准,所以一些其他的测试工具也能使用xml文件。

这里我们只是运行了StringTest中的一个简单的测试,如果实际中失败了,测试报告文件中会说明哪个测试文件,哪个测试方法和哪个断言以及具体的堆栈信息。

5.测试覆盖率报告

测试覆盖率是衡量项目代码质量的一个重要的参考指标。Cobertura是一个优秀的开源测试覆盖率统计工具,Maven 通过 cobertura-maven-plugin插件与之集成,用户可以使用简单的命令为 Maven 项目生成测试覆盖率报告。例如,可以运行如下命令生成报告:

mvn cobertura:cobertura

接着打开项目目录target/site/cobertura下的index.html,就能看到测试覆盖率报告了,这里就不多赘述了。

6.重用测试代码

优秀的程序员会像对待产品代码一样细心维护测试代码,尤其是那些供具体测试类继承的抽象类,它们能够简化测试代码的编写。还有一些根据具体项目环境对测试框架的扩展,也会被大范围地重用。

在命令行运行mvn package的时候,Maven 会将项目的主代码及资源文件打包,将其安装或部署到仓库之后,这些代码就能为他人使用,从而实现 Maven 项目级别的重用。

默认的打包行为是不会包含测试代码的,因此在使用外部依赖的时候,其构件一般都不会包含测试代码。

然后,在项目内部重用某个模块的测试代码是很常见的需求,可能某个底层模块的测试代码中包含了一些常用的测试工具类,或者一些高质量的测试基类供继承。这个时候Maven用户就需要通过配置maven-jar-plugin将测试类打包,如下:

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-jar-plugin</artifactId>
    <executions>
        <execution>
            <goals>
                <goal>test-jar</goal>
            </goals>
        </execution>
    </executions>
</plugin>

maven-jar-plugin插件有两个目标,分别是jar和test-jar,jar通过Maven的内置绑定在default生命周期的package阶段,其行为就是对项目主代码进行打包,而test-jar并没有内置绑定,因此我们上面的配置就是显式的声明该目标来打包测试代码。

通过 mvn help:describe -Dplugin=jar -Ddetail可以知道,jar和test-jar的默认绑定周期阶段就是package阶段,所以我们这里的配置默认就是绑定到了package阶段,所以运行mvn clean package可以发现:

maven-jar-plugin插件的两个目标jar和test-jar都执行了,分别打包了项目的主代码和测试代码。

然后其他的Maven项目就可以引用测试代码的构建依赖了,例如


这里声明的依赖,有一个特殊的元素<type>,所有的测试包构件都是用特殊的test-jar打包类型。而且这一类型都是用test的scope。

有关Maven知识点-插件-maven-surefire-plugin简介的更多相关文章

  1. ruby - 如何每月在 Heroku 运行一次 Scheduler 插件? - 2

    在选择我想要运行操作的频率时,唯一的选项是“每天”、“每小时”和“每10分钟”。谢谢!我想为我的Rails3.1应用程序运行调度程序。 最佳答案 这不是一个优雅的解决方案,但您可以安排它每天运行,并在实际开始工作之前检查日期是否为当月的第一天。 关于ruby-如何每月在Heroku运行一次Scheduler插件?,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.com/questions/8692687/

  2. ruby-on-rails - 无法使用 Rails 3.2 创建插件? - 2

    我对最新版本的Rails有疑问。我创建了一个新应用程序(railsnewMyProject),但我没有脚本/生成,只有脚本/rails,当我输入ruby./script/railsgeneratepluginmy_plugin"Couldnotfindgeneratorplugin.".你知道如何生成插件模板吗?没有这个命令可以创建插件吗?PS:我正在使用Rails3.2.1和ruby​​1.8.7[universal-darwin11.0] 最佳答案 随着Rails3.2.0的发布,插件生成器已经被移除。查看变更日志here.现在

  3. HBase Region 简介和建议数量&大小 - 2

    Region是HBase数据管理的基本单位,region有一点像关系型数据的分区。region中存储这用户的真实数据,而为了管理这些数据,HBase使用了RegionSever来管理region。Region的结构hbaseregion的大小设置默认情况下,每个Table起初只有一个Region,随着数据的不断写入,Region会自动进行拆分。刚拆分时,两个子Region都位于当前的RegionServer,但处于负载均衡的考虑,HMaster有可能会将某个Region转移给其他的RegionServer。RegionSplit时机:当1个region中的某个Store下所有StoreFile

  4. ruby-on-rails - 您希望看到哪些 Rails 插件? - 2

    您认为可以作为插件很好地存在于您的Rails应用程序中必须实现的哪些行为?您过去曾搜索过哪些插件功能但找不到?哪些现有的Rails插件可以改进或扩展,如何改进或扩展? 最佳答案 我希望在管理界面中看到一个引擎插件,它提供了应用程序中所有模型的仪表板摘要,以及可配置的事件图表。 关于ruby-on-rails-您希望看到哪些Rails插件?,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.com/questio

  5. ruby - vagrant 从 github 安装插件 - 2

    我们正在使用Vagrant进行部署,我们最终希望将此集群部署在Rackspace上。vagrant-rackspace插件是一个自然的选择,但它有一些错误,这些错误未包含在最新的0.1.1版本中(notablythatvagrantprovisiondoesn'twork)。我已经在我的personalfork中解决了这个问题通过合并其他人的工作来对存储库进行改造。是否可以从github安装vagrant插件?显而易见的事情没有奏效:[unix]$vagrantplugininstallvagrant-rackspace--plugin-sourcehttps://github.com

  6. ruby - 我怎样才能更好地了解/了解更多关于 Ruby 的知识? - 2

    按照目前的情况,这个问题不适合我们的问答形式。我们希望答案得到事实、引用或专业知识的支持,但这个问题可能会引发辩论、争论、投票或扩展讨论。如果您觉得这个问题可以改进并可能重新打开,visitthehelpcenter指导。关闭9年前。我最近开始学习Ruby,这是我的第一门编程语言。我对语法感到满意,并且我已经完成了许多只教授相同基础知识的教程。我已经写了一些小程序(包括我自己的数组排序方法,在有人告诉我谷歌“冒泡排序”之前我认为它非常聪明),但我觉得我需要尝试更大更难的东西来理解更多关于Ruby.关于如何执行此操作的任何想法?

  7. IDEA使用LeetCode插件 - 2

    前言我们习惯用idea编写、调试代码,在LeetCode上刷题时,如果能够在IDEA编写代码,并且做好代码管理,是一件事半功倍的事情。对于后续复习题目,做笔记也会非常便利。本文目的在于介绍LeetCodeEditor的使用,以及配置工具类,最终目录结构如下:note:放置笔记src:放置代码leetcode.editor.cn:插件LeetCodeEditor自动生成utils:自定义的工具包,可用于自动化输入测试用例,定义题目需要的类(结构体)out:运行测试时自动生成LeetCodeEditorGitHub:https://github.com/shuzijun/leetcode-edit

  8. regex - Ruby 是否有类似于 Perl 6 语法的插件? - 2

    多年来,Perl一直是我首选的编程语言工具之一。Perl6语法看起来像是一个很棒的语言特性。我想知道是否有人开始为Ruby做这样的事情。 最佳答案 如果您想在Ruby中使用实际的Perl6语法,最好的选择是Cardinal,Parrot上的ruby​​编译器。它目前尚未完成并且非常缓慢,但我非常希望它最终成为一个可行的ruby​​实现。它目前大部分处于非事件状态,等待Parrot中的一些基础架构更改以支持改进的解析速度和其他功能。 关于regex-Ruby是否有类似于Perl6语法的插件

  9. ruby-on-rails - 你为 Rails 推荐哪个状态机插件? - 2

    关闭。这个问题不符合StackOverflowguidelines.它目前不接受答案。要求我们推荐或查找工具、库或最喜欢的场外资源的问题对于StackOverflow来说是偏离主题的,因为它们往往会吸引自以为是的答案和垃圾邮件。相反,describetheproblem以及迄今为止为解决该问题所做的工作。关闭9年前。Improvethisquestion我正在为Rails3/ActiveRecord项目寻找一个相对简单的状态机插件。我做了一些研究并提出了以下插件:转换:https://github.com/qoobaa/transitions从旧的ActiveRecord状态机库中提取

  10. ruby-on-rails - 使用模块扩展带有 "has_many"的插件中的模型 - 2

    我在引擎样式插件中有一些代码,其中包含一些模型。在我的应用程序中,我想扩展其中一个模型。通过在初始值设定项中包含一个模块,我已经设法将实例和类方法添加到相关模型中。但是我似乎无法添加关联、回调等。我收到“找不到方法”错误。/libs/qwerty/core.rbmoduleQwertymoduleCoremoduleExtensionsmoduleUser#InstanceMethodsGoHere#ClassMethodsmoduleClassMethodshas_many:hits,:uniq=>true#nomethodfoundbefore_validation_on_crea

随机推荐