事件起因于top的一个测试工程在hudson上构建时,发现传入的参数不起作用,推测其原因是maven的版本问题,自从maven2.0.9升级到2.1.0以后,出现此问题。经过本地用不同版本的maven测试得以证实:

       建一个简单的测试工程,该工程测试用例只需实现读取系统变量param并打印出来,cmd命令窗口输入:mvn clean –Dparam=abc test运行测试:

       apache-maven-2.1.0打印param结果为:null

       apache-maven-2.0.9打印param结果为:abc

       apache-maven-2.1.0及以上的版本都不能读取到利用 –D 传入的properties

       为什么呢?

       原因在于maven中负责测试的surefire插件,surefire2.3及之前的配置项useSystemClassLoader默认值是false,这使得surefire插件在执行测试的时候是没有用系统的ClassLoader,而是使用一个独立的ClassLoadermaven的进程上执行测试,从surefire2.4开始useSystemClassLoader的默认值是true,而且另外的一个配置forkMode的默认值是once,这就使得surefire在执行测试的时候会由maven进程新建一个子进程出来,在我们的配置中,apache-maven-2.1.0用的是最新的surefire插件,当进行mvn test命令执行测试的时候,当前的mavenjvm进程会新建一个jvm实例用于执行测试,但是利用mvn –D传入的参数param是当前的mavenjvm的配置数据,他不能为新建的jvm实例共享,所以做测试的时候没有读取到param参数。

         解决办法:

1  运行测试的时候传入参数forkMode=never,具体的命令如下:

        mvn clean -Dparam=abc -DforkMode=never test;

        这样测试用例就可以读取param打印出来:abc

         hudson中做构建时,需要配置工程属性,具体为:Buildmaven2goalsmvn命令中加入此参数,图示如下:

关于hudson上的工程传入参数无效的总结

          工作原理是:forkMode=never使得useSystemClassLoader强制为false,使得测试用例在当前的maven进程中执行。这样就可以读取maven进程中配置数据了。

         但是这个办法有副作用,这样会使使用emma或者cobertura的代码覆盖率工具的工程得到的代码覆盖率为0%,推测应该是ClassLoader变换的原因使得注入的字节码文件失效。并且不利于maven进程的安全性,不推荐这样做。

2  使用surefire配置变量argLine,为之传入参数-Dparam=abc,具体的命令如下:

mvn clean –DargLine=” -Dparam=abc” test;

       hudson中做构建时,需要配置工程属性,假如我们的工程需要传入参数param,这个参数的值有两种选择:abc或者xyz,那么我们需要选择This build is parameterized , 点击add parameter,选择choice,具体配置如下:


关于hudson上的工程传入参数无效的总结

        假如我们的工程需要以matrix方式构建,配置也是一样的道理。

        工作原理:新建的jvm实例会识别argLine并接收其值-Dparam=abc,并再次以此值为传入参数,相当于对新建的jvm运行mvn -Dparam=abc,使得param配置数据加入新建的jvm环境中。

        这里大家可能会问:为什么param不能传给新建的jvm,而argLine却可以,原因是surefire认识argLine而不认识param

        这个方法也不好,会使得在hudson里面的配置不容易理解,副作用未知,所以也不推荐。

3 pom.xmlmaven-surefire-plugin插件的配置中利用<configuration>标签配置surefire插件,具体如下:


关于hudson上的工程传入参数无效的总结

         hudson中,配置就可以以先前的方式进行,假如我们的工程需要传入参数param,这个参数的值有两种选择:abc或者xyz,那么我们需要选择This build is parameterized , 点击add parameter,选择choice,具体配置如下:

关于hudson上的工程传入参数无效的总结

        工作原理:在surefire插件的配置中,name配置了param,当用mvn –D传入param的时候,新建的jvm就可以识别此配置变量,value配置成:${param}可以用于接收param后面跟着的值。

        这个方法最为正规,理论上不应该有副作用,所以推荐。

        这个方法要求大家在hudson建立自己的工程的时候,如果工程需要从hudson传入参数,那么就需要配置自己工程的pom.xml中的surefire插件,需要几个参数就要配几个property

        初学不久,如有理解错误,欢迎并希望大家立刻指正。