简体   繁体   English

如何在maven-shade-plugin创建的Jar中包含测试类?

[英]How to include test classes in Jar created by maven-shade-plugin?

I'm trying to package my test classes in to an executable jar with dependencies using Maven, but I'm struggling to get this right. 我正在尝试使用Maven将我的测试类打包到一个带有依赖项的可执行jar中,但我很难做到这一点。

This is my pom.xml so far: 到目前为止这是我的pom.xml:

<project>
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.c0deattack</groupId>
    <artifactId>executable-tests</artifactId>
    <version>1.0</version>
    <packaging>jar</packaging>

    <name>executable-tests</name>

    <dependencies>
        <dependency>
            <groupId>info.cukes</groupId>
            <artifactId>cucumber-java</artifactId>
            <version>1.0.0</version>
        </dependency>
        <dependency>
            <groupId>info.cukes</groupId>
            <artifactId>cucumber-junit</artifactId>
            <version>1.0.0</version>
        </dependency>

        <dependency>
            <groupId>org.seleniumhq.selenium</groupId>
            <artifactId>selenium-java</artifactId>
            <version>2.21.0</version>
        </dependency>

        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.10</version>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-jar-plugin</artifactId>
                <version>2.4</version>
                <executions>
                    <execution>
                        <goals>
                            <goal>test-jar</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-shade-plugin</artifactId>
                <version>1.6</version>
                <executions>
                    <execution>
                        <phase>package</phase>
                        <goals>
                            <goal>shade</goal>
                        </goals>
                        <configuration>
                            <finalName>cucumber-tests</finalName>
                            <transformers>
                                <transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
                                    <mainClass>cucumber.cli.Main</mainClass>
                                </transformer>
                            </transformers>
                            <artifactSet>
                                <includes>
                                    <include>info.cukes:*</include>
                                </includes>
                            </artifactSet>
                        </configuration>
                    </execution>
                </executions>
                <dependencies>
                    <dependency>
                        <groupId>com.c0deattack</groupId>
                        <artifactId>executable-tests</artifactId>
                        <version>1.0</version>
                        <type>test-jar</type>
                    </dependency>
                </dependencies>
            </plugin>
        </plugins>
    </build>
</project>

When I execute mvn clean package the build creates 3 jars: 当我执行mvn clean package ,构建会创建3个jar:

  • executable-tests-1.0.jar // built by the mvn package phase executable-tests-1.0.jar //由mvn包阶段构建
  • executable-tests-1.0-teststjar // built by the jar-plugin executable-tests-1.0-teststjar //由jar-plugin构建
  • cucumber-tests.jar // build by the shade-plugin cucumber-tests.jar //由shade-plugin构建

Cucumber-tests.jar contains the info.cuke dependencies but it doesn't contain the executable-tests-1.0-tests.jar . Cucumber-tests.jar包含info.cuke依赖项,但它不包含executable-tests-1.0-tests.jar

I've done all sorts of things to try and have the test classes included but nothing has worked, what am I missing? 我已经做了各种各样的尝试,包括测试课程,但没有任何工作,我错过了什么?

Edit: I've pushed my example project to GitHub if any one fancies playing around with it :) https://github.com/C0deAttack/ExecutableTests 编辑:我已经将我的示例项目推送到GitHub,如果有任何人想玩它:) https://github.com/C0deAttack/ExecutableTests

Answering late, but got a working solution which may help future visitors of this question. 回答很晚,但得到了一个可行的解决方案,可以帮助未来的访问者这个问题。

I succeed on having a fat jar using only one Maven plugin and including: 我成功使用了一个只使用一个Maven插件的胖罐,包括:

  • The test classes 测试类
  • The application code classes 应用程序代码类
  • External dependencies required by application code (in compile scope) 应用程序代码所需的外部依赖项(在compile范围内)
  • External dependencies required by the test code (in test scope) 测试代码所需的外部依赖关系(在test范围内)

Which basically means a fat jar with the addition of test classes (and their dependencies). 这基本上意味着增加了测试类(及其依赖项)的胖罐。 The Maven Jar Plugin and its test-jar goal would not suit this need. Maven Jar插件及其test-jar目标不适合这种需求。 The Maven Shade Plugin and its shadeTestJar option would not help neither. Maven Shade插件及其shadeTestJar选项也无济于事。

So, how to create in Maven a fat jar with test classes and external dependencies? 那么,如何在Maven中创建一个带有测试类和外部依赖项的胖罐?

The Maven Assembly Plugin is a perfect candidate in this case. 在这种情况下, Maven Assembly Plugin是一个完美的候选者。

Here is a minimal POM sample: 这是一个最小的POM样本:

<project>
    <modelVersion>4.0.0</modelVersion>
    <groupId>com.sample</groupId>
    <artifactId>sample-project</artifactId>
    <version>1.0-SNAPSHOT</version>

    <build>
        <plugins>
            <plugin>
                <artifactId>maven-assembly-plugin</artifactId>
                <version>2.3</version>
                <configuration>
                    <descriptor>src/main/assembly/assembly.xml</descriptor>
                </configuration>
                <executions>
                    <execution>
                        <id>make-assembly</id>
                        <phase>package</phase>
                        <goals>
                            <goal>single</goal>
                        </goals>
                        <configuration>
                            <archive>
                                <manifest>
                                    <mainClass>com.sample.TestMain</mainClass>
                                </manifest>
                            </archive>
                        </configuration>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>

    <dependencies>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.11</version>
            <scope>test</scope>
        </dependency>
    </dependencies>
</project>

The configuration above is also setting a main class defined in test classes (for a quick check whether it works or not, down on the answer). 上面的配置还设置了在测试类中定义的主类(用于快速检查它是否有效,在答案上)。 But that's not enough. 但这还不够。

You also need to create a descriptor file , in the src\\main\\assembly folder an assembly.xml file with the following content: 您还需要在src\\main\\assembly文件夹中创建一个描述符文件 ,其中包含以下内容的assembly.xml文件:

<assembly
    xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.3"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.3 http://maven.apache.org/xsd/assembly-1.1.3.xsd">
    <id>fat-tests</id>
    <formats>
        <format>jar</format>
    </formats>
    <includeBaseDirectory>false</includeBaseDirectory>
    <dependencySets>
        <dependencySet>
            <outputDirectory>/</outputDirectory>
            <useProjectArtifact>true</useProjectArtifact>
            <unpack>true</unpack>
            <scope>test</scope>
        </dependencySet>
    </dependencySets>
    <fileSets>
        <fileSet>
            <directory>${project.build.directory}/test-classes</directory>
            <outputDirectory>/</outputDirectory>
            <includes>
                <include>**/*.class</include>
            </includes>
            <useDefaultExcludes>true</useDefaultExcludes>
        </fileSet>
    </fileSets>
</assembly>

The configuration above is: 上面的配置是:

  • setting external dependencies to be taken from the test scope (which will also take the compile scope as well) 设置从test范围中获取的外部依赖项(也将采用compile范围)
  • setting a fileset to include compiled test classes as part of the packaged fat jar 设置一个fileset以包含已编译的测试类作为打包的胖jar的一部分
  • setting a final jar with fat-tests classifier (hence your final file will be something like sampleproject-1.0-SNAPSHOT-fat-tests.jar ). 使用fat-tests分类器设置最终jar(因此你的最终文件将类似于sampleproject-1.0-SNAPSHOT-fat-tests.jar )。

How can we test it? 我们怎么测试呢?

Build the jar: 建立jar:

mvn clean compile test-compile assembly:single

Running from the target folder: target文件夹运行:

java -jar sampleproject-1.0-SNAPSHOT-fat-tests.jar

We would get the main (from tests classes) executed. 我们将执行main(来自测试类)。 The main may invoke others tests or application code (and hence require external dependencies, in both compile or test scope) and everything would work fine. main可以调用其他测试或应用程序代码(因此在compiletest范围内都需要外部依赖)并且一切都可以正常工作。


From such a main, you could also invoke all of your test cases as following: 从这样的main,您还可以调用所有测试用例,如下所示:

  • Create a JUni test suite 创建一个JUni测试套件
  • Add to the test suite the concerned tests 将相关测试添加到测试套件中
  • Invoke the test suite from your plain Java main 从普通的Java main调用测试套件

Example of test suite: 测试套件示例:

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 {

}

Note: in this case the test suite is only concerning the AppTest sample test. 注意:在这种情况下,测试套件仅涉及AppTest样本测试。

Then you could have a main class as following: 然后你可以有一个主类如下:

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);
    }
}

The main above would then execute the test suite which will in chain execute all of the configured tests. 然后,上面的主要部分将执行测试套件,该套件将链执行所有已配置的测试。

I've solved my problem a different way; 我以不同的方式解决了我的问题; using two other plugins. 使用另外两个插件。

First I use the maven-dependency-plugin to get the dependencies and unpack them locally, then I use the maven-jar-plugin to create a test-jar and include the classes from the unpacked dependencies. 首先,我使用maven-dependency-plugin来获取依赖项并在本地解压缩,然后我使用maven-jar-plugin创建一个test-jar并包含来自解压缩依赖项的类。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM