博客园  :: 首页  :: 联系 :: 订阅 订阅  :: 管理

Maven+Sonar如何让单元测试只跑一次?

Posted on 2013-01-17 18:39  Bruce Zhang  阅读(2878)  评论(0编辑  收藏  举报
背景:我用Jenkins做CI,并同时加Sonar做单元测试和质量扫描。
大家都知道,让Maven过滤掉单元测试一般会使用 -Dmaven.test.skip=true(即不编译单元测试代码,也不运行单元测试)。
但是如果直接用-Dmaven.test.skip=true会导致Sonar也不跑单元测试。

技巧:使用-Dtest -DfailIfNoTests=false 让单元测试仅仅在Sonar扫描时启动。
解释:
下面是官方对于“test”和“failIfNoTests”的解释:
test String - Specify this parameter to run individual tests by file name, overriding theincludes/excludes parameters. Each pattern you specify here will be used to create an include pattern formatted like **/${test}.java, so you can just type "-Dtest=MyTest" to run a single test called "foo/MyTest.java".
This parameter overrides the includes/excludes parameters, and the TestNGsuiteXmlFiles parameter. Since 2.7.3, you can execute a limited number of methods in the test by adding #myMethod or #my*ethod. For example, "-Dtest=MyTest#myMethod". This is supported for junit 4.x and testNg.
User property istest

 

failIfNoTests Boolean 2.4 Set this to "true" to cause a failure if there are no tests to run. Defaults to "false".
User property isfailIfNoTests.
(1)可以看出“test”参数的标准用法应该是:-Dtest=MyTest#myMethod(使用正则表达式匹配需要运行的单元测试)。
使用“-Dtest”,实质等同于“-Dtest=<空值>”。因此肯定匹配不到任何单元测试类,从而达到跳过单元测试的效果。
(2)使用“-DfailIfNoTests=false”是为了取消因为“-Dtest”导致没有任何单元测试运行而抛出的异常。(有单元测试,但一个都没运行,maven会以任务失败来表示警告
(3)最重要的一点是:Sonar运行时的maven-surefire-plugin竟然不认上述-Dtest的过滤作用。
具体原因没有深究,不过通过比较日志中的maven-surefire-plugin的goal,就能发现端倪了:
maven-surefire-plugin:2.12.4:test (default-test)【正常mvn的goal】
maven-surefire-plugin:2.12.4:test (default-cli) 【sonar的goal】
 坏处:如果单元测试运行失败,或出现运行时异常等,Jenkins JOB的状态不会发生改变。
因为,maven构建时,跳过了单元测试,所以即使单元测试出现问题,Jenkins JOB的状态也不会变化。
并且,Sonar运行的结果也不会影响Jenkins JOB的状态。