如何将测试类包含在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); } } 

然后,上面的主要部分将执行测试套件,该套件将链执行所有已配置的测试。