使用 Maven 进行集成测试的最佳实践?

Posted

技术标签:

【中文标题】使用 Maven 进行集成测试的最佳实践?【英文标题】:Best practices for integration tests with Maven? 【发布时间】:2010-11-16 18:07:04 【问题描述】:

我有一个使用 Maven 构建的项目,它使用 Hibernate(和 Spring)从数据库等中检索数据。

我在项目中对 DAO 的“测试”扩展了 Spring 的 AbstractTransactionalDataSourceSpringContextTests,以便可以将 DataSource 连接到我的测试类中,以便能够实际运行查询/休眠逻辑、获取数据等。

在其他几个项目中,我将这些类型的测试与 HSQL 数据库(内存中或指向文件)结合使用,以便能够在不依赖外部数据库的情况下有效地测试实际的数据库查询逻辑。这很好用,因为它避免了任何外部依赖,并且在运行测试之前数据库的“状态”(每个测试都包装在一个回滚的事务中)是明确定义的。

我很好奇用 Maven 组织这些测试的最佳方式,这实际上是一种松散的集成测试。将这些测试保存在 src/test/java 中感觉有点脏,但从我读到的内容来看,使用 Maven 组织集成测试似乎没有一致的策略或实践。

从我目前阅读的内容来看,似乎我可以使用 Failsafe plugin(或 Surefire 的第二个实例)并将其绑定到 integration-test 阶段,并且我还可以绑定自定义启动或关闭逻辑(例如用于启动/停止 HSQL 实例)到pre-integration-testpost-integration-test。但是,这真的是最好的方法吗?

所以我的问题基本上是 - 用 Maven 组织这个的普遍接受的最佳实践是什么?我在文档中找不到任何一致的答案。

我想要的是:

将单元测试与集成测试分开,因此在test 阶段只运行单元测试 能够将自定义启动/关闭逻辑绑定到pre-integration-testpost-integration-test 将来自集成测试的报告与单元测试 Surefire 报告合并/呈现

【问题讨论】:

将集成测试移动到一个单独的项目中,并将单元测试与源代码保持在同一个项目中。 【参考方案1】:

一个非常简单的方法是使用 JUnit 类别。

然后,您可以在测试阶段轻松运行一些测试,在集成测试阶段运行另一个测试。

只需几分钟,只需 3 个步骤。

    定义标记界面 注释要拆分的类 配置 Maven 插件。

这里给出了一个完整的例子。 https://***.com/a/10381662/1365383

【讨论】:

或者,如果您使用 TestNG,您可以指定测试组:例如单元和集成。【参考方案2】:

codehaus page 有一些指导方针。我发现故障安全插件有点小技巧,它使在 Eclipse 中运行单元测试变得异常复杂。我大致按照您的描述进行。

在 src/itest/java 中定义集成测试 在预集成测试阶段:

清除目标/测试类 使用build-helper-maven-plugin's add-test-source 目标添加测试源位置 使用自定义 Mojo 从配置中删除 src/test/java,这样单元测试就不会再次编译(我不太喜欢这样,但需要保持单元测试和集成测试的分离)。李> 使用编译器插件编译集成测试

然后在集成测试阶段,使用 surefire-plugin 运行测试。

最后,将所有整理目标绑定到集成后测试阶段(尽管通常不需要它们,因为您可以使用测试 teardown() 进行整理)。

由于报告阶段已经过去,我还没有找到合并测试结果的方法,但我 倾向于将集成测试视为额外的奖励,因此只要他们通过报告就不是那么重要了。

更新:我认为值得指出的是,您可以在集成测试中运行 Jetty,而不是使用 jetty 目标。这使您可以更好地控制测试。您可以从this answer 和参考的博客中获取更多详细信息。

【讨论】:

你真的需要删除单元测试吗?在集成测试时再次运行它们当然不是一个坏主意。 一般来说你是对的。再次运行单元测试并没有什么坏处,但我在服务器上有 100 多个项目,必须进行一些优化来管理可用硬件内的负载。 很公平,你有一个相当重要的特殊情况 :-) 这个答案在 2016 年仍然有效吗?看起来 mvn 故障安全插件是一个更好的方法。【参考方案3】:

This good blog post 建议三个选项;

1) 用于集成测试的独立模块

2) 不同的源目录

3) 不同的文件名模式

我还没有尝试所有三个,所以不能提供我喜欢的意见。

【讨论】:

正确的链接是javamoods.blogspot.com/2009/12/…【参考方案4】:

我更喜欢第二个选项,不同的源目录,但我发现必须以 IT 结束集成测试或排除包,这很烦人。

为了避免这种情况,我最终得到了这个配置:

<properties>
    <testSource>src/test/java</testSource>
    <testSourceResource>src/test/resources</testSourceResource>
</properties>
<build>
    <testSourceDirectory>$testSource</testSourceDirectory>
    <testResources>
            <testResource>
            <directory>$testSourceResource</directory>
            </testResource>
        </testResources>
.....
.....

然后我覆盖不同配置文件中的两个变量以进行集成和验收测试:

<profiles>
  <profile>
   <id>acceptance-tests</id>
   <properties>
    <testSource>src/acceptance-test/java</testSource>
    <testSourceResource>src/acceptance-test/resources</testSourceResource>
   </properties>
  </profile>
 <profile>
   <id>integration-tests</id>
    <properties>
    <testSource>src/integration-test/java</testSource>
    <testSourceResource>src/integration-test/resources</testSourceResource>
    </properties>
  </profile>
.....
.....
.....

【讨论】:

以上是关于使用 Maven 进行集成测试的最佳实践?的主要内容,如果未能解决你的问题,请参考以下文章

集成测试方法与最佳实践

使用 Airflow 进行集成测试

针对docker中的服务进行集成测试

在 Maven/Junit/DBUnit 项目的集成测试之前/之后创建/删除数据库的最佳方法?

SoapUI实践:自动化测试压力测试持续集成

SoapUI实践:自动化测试压力测试持续集成