Jenkins随机构建失败

时间:2014-03-12 13:51:26

标签: java unit-testing maven jenkins noclassdeffounderror

所以这个问题会有点模糊,我道歉,但我甚至不知道从哪里开始。我们使用Jenkins在夜间自动化一些构建。我们用maven执行我们的构建。有一段时间,一切都很好。我们有findbugs,代码覆盖率结果和成功构建的稳定历史。突然之间,似乎已经出现了我们在运行单元测试时获得随机NoClassDefFound异常的情况。它非常奇怪,因为在此之前,日志消息清楚地表明它构建了源并成功。然后单元测试开始运行,它们会立即死于上述异常。我们最近对Jenkins进行了更新,但我并不完全相信它与它有很大关系。真正奇怪的是,构建并不总是因此异常而失败。有时它们会跑得很好,有时会很快失败。就失败的特定单元测试或无法找到的特定类而言,失败并不一致。虽然它们似乎围绕着相同的一小组类和单元测试,但似乎没有任何真正的模式。

有没有其他人在jenkins上使用maven构建了吗?我真的不知道该怎么做。日志消息并不完全有用,我不知道我可以对Jenkins配置做些什么来从失败的构建中获得更好的调试信息。如果有人有任何想法,我可以收集任何人可能需要的信息。以下是来自最近失败的构建之一的示例堆栈跟踪:

com.ipti.ptl.common.problems.detectors.CMDRProblemDetectorTest.afterPropertiesSetTest

Failing for the past 3 builds (Since Unstable#411 )
Took 18 ms.
Error Message

com/ipti/hardware/bcicinterface/CPacketReceivedArgs
Stacktrace

java.lang.NoClassDefFoundError: com/ipti/hardware/bcicinterface/CPacketReceivedArgs
    at java.net.URLClassLoader$1.run(URLClassLoader.java:366)
    at java.net.URLClassLoader$1.run(URLClassLoader.java:355)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.net.URLClassLoader.findClass(URLClassLoader.java:354)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
    at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:308)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
    at java.lang.Class.getDeclaredMethods0(Native Method)
    at java.lang.Class.privateGetDeclaredMethods(Class.java:2521)
    at java.lang.Class.getDeclaredMethods(Class.java:1845)
    at com.ipti.common.eventbus.EventBus.subscribe(EventBus.java:107)
    at com.ipti.ptl.common.problems.detectors.CMDRProblemDetector.afterPropertiesSet(CMDRProblemDetector.java:23)
    at com.ipti.ptl.common.problems.detectors.CMDRProblemDetectorTest.afterPropertiesSetTest(CMDRProblemDetectorTest.java:37

2 个答案:

答案 0 :(得分:1)

我经历过类似的事情。我们学习了两个重要提示,以保持一致性:

  1. 每次构建时,将构建配置为“Checkout fresh sources”。有时事情可能会变得陈旧
  2. 检查您是否使用clean packageclean installinstall会将人工制品存储在运行Jenkins的用户本地的.m2存储库中。如果不是这样,任何给定项目可能必须在构建时从其配置的存储库下载它的依赖项。我建议使用clean install只是为了让本地人工制品准备好依赖构建。
  3. 根据这两个规则仔细检查每个Jenkins构建是很重要的。相互依赖的项目之间的不一致也是随机混淆的根源。

答案 1 :(得分:1)

除了@jmkgreen所说的,或者如果你尝试这些步骤并且他们没有解决问题,我会检查工件的类路径中的问题。 Surefire和JUnit不保证测试将按特定顺序运行。以不同的顺序运行测试可能会导致以不同的顺序加载类,并导致这些奇怪的问题。 This blog post有一个很好的解释。

如果这似乎正在发生,那么您可以采取一些步骤来清理工件的依赖关系。

删除所有不需要的依赖项

确保每个依赖项只包含一个版本(例如,只有一个Spring框架)。

特别注意组ID或工件ID已更改的工件。对于这些情况,Maven依赖关系解析过程无法检测到一个工件应该覆盖另一个并包括两者。这可能会导致有趣的,有时甚至是非确定性的问题。一个例子是spring.jarspring-core.jar

如果应用程序包含多个支持相同功能的依赖项,则需要手动排除不需要的依赖项,如Maven documentation中所述。

确保相关的依赖项都使用相同的版本

例如,如果项目包含多个Spring工件(spring-core,spring-jdbc,spring-aop等),请确保所有版本的版本相同。使用dependencyManagement或根据需要添加直接依赖项以使版本保持一致。

将所有-all - 类型依赖项替换为其组成部分

......只有项目所需的那些。 -all jar可能包含运行库所需的每个类 - 重新打包到Maven的依赖项解析过程无法获取的jar文件中 - 而不是将它们作为依赖项引用。

例如,mockito-all contains a repackaged version of Hamcrest,可以conflict与任何其他版本的Hamcrest项目想要使用(并且可能不会导致难以解决的问题,直到运行时!)。