TeamCity会在测试失败时运行构建步骤。

26
我遇到了关于Teamcity的问题,即使之前的步骤失败,它仍继续运行构建步骤。
我的构建配置的最后一步是部署我的网站,如果任何测试失败,我不希望它这样做。
每个构建步骤都设定为只有在所有先前的步骤都成功执行后才能执行。
在“构建失败条件”选项卡中,我已经勾选了以下选项:
-build process exit code is not zero
-at least one test failed
-an out-of-memory or crash is detected (Java only)

这不起作用 - 即使测试失败,TeamCity也会部署我的站点,为什么?
我甚至尝试添加一个额外的构建失败条件,它将查找构建日志中的特定文本(即“Test Run Failed.”)
在概述页面中查看已完成的测试时,您可以看到最新构建的错误消息:
“Test Run Failed.” text appeared in build log
但是它仍然会进行部署。
有人知道如何修复这个问题吗?看起来这个问题已经存在很长时间了,here
显然有一个解决方法: > 到目前为止,我们认为这个功能不是非常重要,因为有一个明显的解决方法:脚本可以检查必要的条件,并且在 TeamCity 中配置不生成艺术品。 > 例如,一个脚本可以将艺术品从临时目录移动到指定的目录中,在完成之前并且在构建操作成功的情况下发布艺术品。
但我不清楚如何确切地做到这一点,而且这似乎也不是最好的解决方案。任何帮助都将不胜感激。
编辑:我也能够通过快照依赖解决问题,我将有一个单独的“部署”构建与测试构建有依赖关系,如果测试失败,它现在不会运行。 对于设置依赖项非常有用。

尽管你通过一个解决方法解决了自己的问题,但我认为亚当的答案更适合你描述的情况。考虑将他的答案标记为已接受。 - John Korsnes
是的,我不太确定,只因为我的解决方法更简单,但这是一个很好的答案,我已经重新分配了。 - DevDave
5个回答

27

这是一个已知问题,自TeamCity 7.1以来就存在(参见http://youtrack.jetbrains.com/issue/TW-17002),在TeamCity 8.x+中已得到修复(请参阅此答案)。

TeamCity区分失败的构建和失败的构建步骤。虽然一个失败的单元测试会使整个构建失败,但不幸的是,TeamCity仍然认为测试步骤本身是成功的,因为它没有返回非零错误代码。因此,后续步骤将继续运行。

已经提出了各种解决方法,但我发现它们要么需要非微不足道的设置,要么会影响TeamCity中的测试体验。

然而,在查看来自@arex1337的建议后,我们找到了一个简单的方法来让TeamCity实现我们想要的功能。只需在现有测试步骤之后添加一个额外的Powershell构建步骤,其中包含以下内联脚本(将YOUR_TEAMCITY_HOSTNAME替换为您的实际TeamCity主机/域名):

$request = [System.Net.WebRequest]::Create("http://YOUR_TEAMCITY_HOSTNAME/guestAuth/app/rest/builds/%teamcity.build.id%")
$xml = [xml](new-object System.IO.StreamReader $request.GetResponse().GetResponseStream()).ReadToEnd()
Microsoft.PowerShell.Utility\Select-Xml $xml -XPath "/build" | % { $status = $_.Node.status }

if ($status -eq "FAILURE") {
    throw "Failing this step because the build itself is considered failed. This is our way to workaround the fact that TeamCity incorrectly considers a test step to be successful even if there are test failures. See http://youtrack.jetbrains.com/issue/TW-17002"
}

这个内联的PowerShell脚本只是使用TeamCity REST API来询问整个构建本身是否被视为失败(变量%teamcity.build.id%将在执行该步骤时由TeamCity替换为实际的构建ID)。如果整个构建被视为失败(例如由于测试失败),那么这个PowerShell脚本会抛出一个错误,导致进程返回非零错误代码,结果使得单个构建步骤本身也被视为不成功。此时,后续步骤可以被阻止运行。

请注意,该脚本使用guestAuth,需要启用TeamCity访客帐户。或者,您可以改用httpAuth,但需要更新脚本以包括TeamCity用户名和密码(例如:http://USERNAME:PASSWORD@YOUR_TEAMCITY_HOSTNAME/httpAuth/app/rest/builds/%teamcity.build.id%)。

因此,在加入此附加步骤后,所有设置为“仅当所有前面的步骤都成功时才执行”的后续步骤将被跳过,如果有任何先前的单元测试失败,我们使用这种方法防止自动部署,直到JetBrains解决了问题。

感谢@ arex1337提供的想法。


有一种更简单的方法可以直接获取构建状态,而无需解析XML:/guestAuth/app/rest/builds/%teamcity.build.id%/status - arni
1
在PowerShell中抛出错误似乎不会返回错误代码。我使用了“exit 1”代替。 - arni
正如@arni所提到的,您需要输出一个非零的退出代码,以便TeamCity检测构建失败。使用“exit 1”而不是抛出错误。 - Karl Cassar

24

仅为避免混淆,这个问题已经在Team City v8.x中得到解决,现在我们不需要那些解决方法。

您可以通过“执行步骤”选项指定步骤执行策略:

只有构建成功 - 在开始步骤之前,构建代理向服务器请求构建状态,如果状态失败,则跳过该步骤。

https://confluence.jetbrains.com/display/TCD8/Configuring+Build+Steps

当然,如果至少有一个单元测试失败,您需要使构建失败:

https://confluence.jetbrains.com/display/TCD8/Build+Failure+Conditions

在“构建失败条件”页面的“失败构建”区域中,指定TeamCity何时会失败:

至少有一个测试失败:选中此选项,以标记构建失败,如果构建至少有一个测试失败。


这是正确的答案。勾选“至少有一个测试失败”和“构建运行器记录了错误消息”(以防万一)为我们解决了这个问题。节省了时间、精力和维护混乱,避免了使用PowerShell的路线! - starmandeluxe

3
这是一项已知的TeamCity问题,你已经发现了,在他们的问题跟踪器中有一组链接问题。希望这个问题能在下一个TeamCity版本(8.x版本)中得到解决。
同时,我们找到了解决这个问题的方法(适用于6.5.5版本),即在后续步骤中下载测试结果文件,然后解析以检查是否存在任何测试失败,并返回错误代码,从而正确地中断构建(执行我们需要的任何清理作为该故障的一部分),这对您可能也有效。

1
团队城市构建失败并不意味着它会停止构建并发布构建产物,如果您的构建按照TeamCity所需的方式提供了构建输出文件,它只会正确更新构建状态。
但是,您可以通过修改构建脚本来在测试用例失败时停止构建过程。如果您正在使用MSBuild,则ContinueOnError="false"将实现此功能。

我在部署构建步骤中设置了这个值,@RinoTom,然后它仍然被部署了。 - DevDave
如果我有任何混淆,对此很抱歉。ContinueOnError 是默认设置为 false 的东西。因此,在任何构建步骤中可能不需要明确指定它。但是,在某些构建步骤中,它可能被设置为 true。因此,您需要检查其中的一个是否为 true 并将其更改回来。最有可能的情况是,构建失败的地方就在目前这个阶段。部署构建步骤可以继续进行,无需更改。 - RinoTom

0
最终,我通过快照依赖解决了问题。我创建了一个单独的“部署”构建,它依赖于测试构建,如果测试失败,它就不会运行。 这个链接 对设置依赖关系非常有用。

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