我该把Java库的测试支持代码放在哪里?

8
我有一个Maven项目,作为其他项目中使用的库。设置非常标准:src/main 包含库代码,src/test 包含 src/main 的测试用例。
假设我有一个名为 foo 的项目依赖于这个库。 foo 也有测试用例。为了帮助在使用我的库的代码时编写 foo 的测试,我想给 foo提供一个支持框架来编写测试(如设置模拟环境)。
我应该把这个支持代码放在哪里呢?
  • 不能放在 src/main 中,因为它不是用于生产的。
  • 不能放在 src/test 中,因为将 foo 的测试与库的测试建立依赖会使类路径中添加太多垃圾文件(如 logback-test.xml 配置文件,从未执行过的测试等)。
我可以将代码放入新的模块中,但它与 src/main 中的代码紧密耦合,因此我想将其保留在同一项目中(还允许测试支持代码访问包私有字段和方法)。
同时,src/test 中的代码应该能够访问它,以便我可以使用它来编写自己的单元测试。
在Maven中有哪些选项可以将它保留在同一项目中,但仍然与 src/mainsrc/test 分离得很清楚?我是否可以创建第三个输出JAR,例如 src/test-support ?或者,我应该把代码放入 src/test 中,然后使用JAR插件中的过滤器仅包含支持代码?
2个回答

3

你可以使用Maven Jar插件来完成此操作。

Maven Jar插件

由于你正在使用Maven,你可以剪切一个包含你想在foo中使用的库的项目的单独构件,并添加以下插件来创建另一个jar构件:

  <plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-jar-plugin</artifactId>
    <version>2.3.2</version>
    <executions>
       <execution>
          <goals>
              <goal>test-jar</goal>
          </goals>
       </execution>
    </executions>
  </plugin>

这将在该项目中创建第二个jar文件,其中包括src/test目录中的所有内容。 测试Jar 您可以使用一些过滤器剪切掉该jar文件中不需要的内容。
然后,要使用此库,您需要在foo中将其作为依赖项包含。
 <dependency>
    <groupId>your.group</groupId>
    <artifactId>parent-artifact-id</artifactId>
    <version>1.0.0</version>
    <type>test-jar</type>
    <scope>test</scope>
 </dependency>

为了更好地区分项目,您还可以创建一个只包含框架测试 jar 的测试项目。
详见 Maven Jar 插件文档中的“如何创建包含测试类的 jar 文件”(推荐方法)。

是否可以创建一个普通的测试jar(包含src/test中的所有代码),以及另一个带有过滤文件集的jar? - Aaron Digulla
可以通过使用不同的分类器两次运行插件来实现这一点。http://maven.apache.org/plugins/maven-jar-plugin/usage.html - Bob Paulin
不起作用 :-( 目标 test-jar 忽略了 classifier 中的值并始终使用 tests。使用目标 jar 时,它按预期工作,但是它只查找 src/main 中的类,因此 JAR 始终为空。 - Aaron Digulla
为什么?通常情况下,当代码拥有更多的模块时,它会更加模块化。 - Daniel Kaplan
@tieTYT:这样会更模块化,但是测试覆盖率将为0%... - Aaron Digulla
显示剩余3条评论

0
这是一个POM片段,它将主JAR分成普通构件和“JUnit支持JAR”:
<build>
    <plugins>
        <plugin>
            <artifactId>maven-jar-plugin</artifactId>
            <executions>
                <execution>
                    <id>default-jar</id>
                    <phase>package</phase>
                    <goals>
                        <goal>jar</goal>
                    </goals>
                    <configuration>
                        <archive>
                            <index>true</index>
                            <manifest>
                                <addDefaultImplementationEntries>true</addDefaultImplementationEntries>
                            </manifest>
                        </archive>
                        <excludes>
                            <exclude>**/junit/**</exclude>
                        </excludes>
                    </configuration>
                </execution>

                <execution>
                    <id>junit-jar</id>
                    <phase>package</phase>
                    <goals>
                        <goal>jar</goal>
                    </goals>
                    <configuration>
                        <classifier>junit</classifier>
                        <archive>
                            <index>true</index>
                            <manifest>
                                <addDefaultImplementationEntries>true</addDefaultImplementationEntries>
                            </manifest>
                        </archive>
                        <includes>
                            <include>**/junit/**</include>
                        </includes>
                    </configuration>
                </execution>

                <execution>
                    <id>test-jar</id>
                    <goals>
                        <goal>test-jar</goal>
                    </goals>
                </execution>
            </executions>
        </plugin>

    </plugins>
</build>

简而言之,它会查找任何名称中带有junit的包,并将其放入JUnit JAR中,从普通构件中排除。
如果普通JAR的坐标为:
<groupId>com.group</groupId>
<artifactId>foo</artifactId>

然后,您只需添加<classifier>junit</classifier>即可获取JUnit支持代码:

<groupId>com.group</groupId>
<artifactId>foo</artifactId>
<classifier>junit</classifier>

因此,要使用它,依赖于com.group:foo的POM将如下所示:

<dependency>
    <groupId>com.group</groupId>
    <artifactId>foo</artifactId>
    <version>...</version>
</dependency>
<dependency>
    <groupId>com.group</groupId>
    <artifactId>foo</artifactId>
    <version>...</version>
    <classifier>junit</classifier>
    <scope>test</scope>
</dependency>

有时候,你需要使用JUnit来编译你的“JUnit支持JAR”文件。如果是这种情况,请使用:
<dependency>
    <groupId>junit</groupId>
    <artifactId>junit</artifactId>
    <scope>compile</scope>
    <optional>true</optional>
</dependency>

将JUnit包含到构建中。 这将使得依赖项在编译时可用,但不会泄漏给其他人。

你可以将这两个独立的jar插件任务绑定到不同的阶段。因此,当你运行mvn.bat test install时,测试阶段可以创建第一个jar包,而安装阶段则可以创建第二个jar包,对吧?这只是一个可以添加的想法。 - djangofan
我想我可以这样做,但是有什么好处呢? - Aaron Digulla

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接