【问题标题】:Maven-surefire-plugin tests fail in Jenkins build but run successfully locally?Maven-surefire-plugin 测试在 Jenkins 构建中失败但在本地成功运行?
【发布时间】:2016-03-17 23:43:07
【问题描述】:

我有一个由 maven-surefire-plugin 执行测试的 maven 项目。我观察到并一直在处理的一个奇怪现象是在本地运行

mvn clean install

执行我的测试,生成成功的构建,0 次失败和 0 次错误。

现在,当我将此应用程序部署到 Jenkins 尝试构建的远程存储库时,我会收到各种随机的 EasyMock 错误,通常是这样的:

java.lang.IllegalStateException: 3 matchers expected, 4 recorded. at org.easymock.internal.ExpectedInvocation.createMissingMatchers

这是一个被继承的遗留应用程序,我们知道,如果没有明显错误地使用 EasyMock,其中许多测试都有缺陷,但我处于这样一种状态,即通过测试执行,我在本地成功构建,但在 Jenkins 中没有.

我知道这些测试的执行顺序无法保证,但我想知道如何自省 Jenkins 构建管道与本地的不同之处以帮助识别问题?

我能做些什么来强制以本地完成的方式执行测试吗?在这一点上,我只是简单地排除了许多麻烦的测试类,但似乎无论我看到多少次 Jenkins 失败,我要么修复问题,要么排除测试类,我只是发现它抱怨其他一些测试之前没有提到的类。

任何想法如何处理这种情况?

【问题讨论】:

    标签: java maven unit-testing jenkins maven-surefire-plugin


    【解决方案1】:

    我已经尝试过类似的情况,我的原因显然是测试实现的一些并发问题

    并且,在阅读您的评论后:

    我实际上做了什么来修复它(就像魔术一样,我是对的吗?)是针对 maven-surefire 插件,我设置了属性reuseForks=false,forkCount=1C,这只是 1*(机器的 CPU 数量)。

    ...我更加确信您的测试存在并发问题。并发性不容易诊断,特别是当您的实验在一个 CPU 上运行良好时。但是当您在另一个系统(通常更快或更慢)上运行它时,可能会出现竞争条件。

    我强烈建议您逐一检查您的测试,并确保每个测试逻辑隔离

    • 它们不应依赖于预期的先前状态(文件、数据库等)。相反,他们应该在每次执行之前准备适当的设置
    • 如果他们同时修改可能会干扰其他测试执行的公共资源(文件、数据库、单例等),则必须尽可能多地同步每个断言,并考虑到其初始状态未知:李>

    错误的测试:

    MySingleton.getInstance().put(myObject);
    assertEquals(1, MySingleton.getInstance().size());
    

    正确的测试:

    synchronized(MySingleton.getInstance())
    {
        MySingleton.getInstance().put(myObject);
        assertTrue(MySingleton.getInstance().contains(myObject));
    }
    

    审查的一个良好起点是检查其中一个失败的测试并向后跟踪执行以找出失败的根本原因。

    明确设置测试的顺序不是一个好习惯,即使我知道这是可能的,我也不会向您推荐它,因为它只会隐藏问题的实际原因.想想,在真实的生产环境中,执行的顺序通常是没有保证的。

    【讨论】:

    • 完全同意这里所说的一切,并且您发现的问题确实是许多(如果不是大多数)测试的问题。然而,它们有成百上千个,重写或重构许多测试不是我们现在有时间做的事情。同样不幸的是,修复它们也不容易,因为许多在构建中失败的测试在本地成功,并且错误通常来自 EasyMock,并且通常描述性不足以轻松诊断。
    • 是的,我明白了...好吧,您对reuseForksforkCount 的尝试已经足够聪明了。也看看threadCount*parallel参数:maven.apache.org/surefire/maven-surefire-plugin/test-mojo.html
    【解决方案2】:

    JUnit 测试运行顺序是不确定的。

    两台机器上的 Java 和 Maven 版本是否相同?如果是,请确保您使用的是最新的 maven-surefire-plugin 版本。此外,请确保使用带有 Maven 构建步骤的 Freestyle Jenkins 作业,而不是 Maven 项目类型。使用正确的 Jenkins 构建类型既可以彻底解决构建问题,也可以为您提供更好的错误,以便您诊断实际问题。

    您可以打开 Maven 调试日志以查看运行测试的顺序。每个测试都应设置(并可能拆除)自己的测试数据,以确保测试可以独立运行。也许看到测试顺序会给你一些线索,告诉你哪些类不恰当地依赖于其他类。并且 - 如果应用程序使用缓存,请确保在测试之间清除缓存(或根据测试需要做的明确填充)。还可以考虑一次运行一个包以隔离罪魁祸首 - 多个 Surefile 插件执行可能很有用。

    同时检查应用程序是否存在类路径问题。 This answer 有一些清理类路径的建议。

    还有另一种可能性:切换到更高版本的 JUnit 可能会有所帮助 - 除非应用程序使用的是 Spring 2.5.6.x。如果应用程序使用 Spring 2.5.6.x 并且无法升级,则可能使用的最高版本的 JUnit 4.x 是 4.4。 JUnit 的更高版本是not compatible with Spring Test 2.5.6,可能会导致难以诊断的测试错误。

    【讨论】:

    • 我实际上做了什么来修复它(就像魔术一样,我是对的吗?)是针对 maven-surefire 插件,我设置了属性reuseForks=false,forkCount=1C,这只是 1*(机器的 CPU 数量)。
    猜你喜欢
    • 2017-09-01
    • 2015-03-26
    • 2019-07-06
    • 1970-01-01
    • 2015-11-15
    • 2019-01-14
    • 1970-01-01
    • 2019-07-14
    • 1970-01-01
    相关资源
    最近更新 更多