如何将测试类包含在Maven jar中并执行它们?
在Maven项目中,我在同一个包中有测试类和源类,但是在不同的物理位置。
.../src/main/java/package/** <-- application code .../src/test/java/package/** <-- test code
访问测试类中的源类没有问题,但是我想在main方法中运行一个测试运行器并访问AllTest.class
这样我就可以创建jar并执行我的测试。
public static void main(String[] args) { // AllTest not found Result result = JUnitCore.runClasses(AllTest.class); for (Failure failure : result.getFailures()) { System.out.println(failure.toString()); } System.out.println(result.wasSuccessful()); }
但它不起作用,因为我无法访问测试代码。 我不明白,因为他们在同一个包中。
问题 :如何从应用程序类访问测试类? 或者,Maven如何打包包含测试类和执行测试的胖jar?
您不应该从应用程序代码访问测试类,而是在测试范围中创建一个main(相同的main),并为您的项目创建一个额外的工件。
但是,在这个额外的工件(jar)中你需要:
- 测试类
- 应用程序代码类
- 应用程序代码所需的外部依赖项(在
compile
范围内) - 测试代码所需的外部依赖关系(在
test
范围内)
这基本上意味着增加了测试类(及其依赖项)的胖jar。 Maven Jar插件及其test-jar
目标不适合这种需求。 Maven Shade插件及其shadeTestJar
选项也无济于事。
那么,如何在Maven中创建一个带有测试类和外部依赖项的胖jar?
在这种情况下, Maven Assembly Plugin是一个完美的候选者。
这是一个最小的POM样本:
4.0.0 com.sample sample-project 1.0-SNAPSHOT maven-assembly-plugin 2.3 src/main/assembly/assembly.xml make-assembly package single com.sample.TestMain junit junit 4.11 test
上面的配置是在测试类中设置您定义的主类。 但这还不够。
您还需要在src\main\assembly
文件夹中创建一个描述符文件 ,其中包含以下内容的assembly.xml
文件:
fat-tests jar false / true true test ${project.build.directory}/test-classes / **/*.class true
上面的配置是:
- 设置从
test
范围中获取的外部依赖项(也将采用compile
范围) - 设置一个
fileset
以包含已编译的测试类作为打包的胖jar的一部分 - 使用
fat-tests
分类器设置最终jar(因此你的最终文件将类似于sampleproject-1.0-SNAPSHOT-fat-tests.jar
)。
然后,您可以按照以下方式(从target
文件夹)调用main:
java -jar sampleproject-1.0-SNAPSHOT-fat-tests.jar
从这样的主程序中,您还可以调用所有测试用例,如下所示:
- 创建一个JUni测试套件
- 将相关测试添加到测试套件中
- 从普通的Java main调用测试套件
测试套件示例:
import org.junit.runner.RunWith; import org.junit.runners.Suite; import org.junit.runners.Suite.SuiteClasses; @RunWith(Suite.class) @SuiteClasses({ AppTest.class }) public class AllTests { }
注意:在这种情况下,测试套件仅涉及AppTest
样本测试。
然后你可以有一个主类如下:
import org.junit.internal.TextListener; import org.junit.runner.JUnitCore; public class MainAppTest { public static void main(String[] args) { System.out.println("Running tests!"); JUnitCore engine = new JUnitCore(); engine.addListener(new TextListener(System.out)); // required to print reports engine.run(AllTests.class); } }
然后,上面的主要部分将执行测试套件,该套件将链执行所有已配置的测试。