Windows、Gradle 和 Cucumber 组合在生成报告时抛出 IOException
Windows, Gradle and Cucumber combination throws an IOException upon generating reports
我正在开发一个项目,该项目结合使用了 Windows、Java、Groovy、Gradle 和 Cucumber。这种组合在我的 Windows 机器上给我带来了一些我的 *NIX 同事没有遇到的问题。 运行 gradle 构建后,gradle 想要输出一些报告。这些报告的位置和文件名显然是由 Cucumber 测试的定义或输出决定的。不幸的是,所使用的名称不能用作文件名,因此每个测试报告都会出现 IOException。
对于 Cucumber 测试,我们使用以下结构:
Scenario Outline: Receive and parse ReturnItem from Service
Given The message from service return item outlined in <messagePath>
When We process the message
Then XXX posted a message to YYY on topic <topic> with event <eventType>
And payload matches <resultPath>
| messagePath | topic | eventType | resultPath |
| /test/testxml.xml | test_topic | EVENT_TYPE | /result/result.json |
在 运行 之后,我收到以下异常:
Caused by: org.gradle.api.UncheckedIOException: Could not write to file 'C:\xxx\project\build\reports\tests\test\packages\| \test\testxml.xml | test_topic | EVENT_TYPE | \result\result.html'.
at org.gradle.internal.IoActions$TextFileWriterIoAction.execute(IoActions.java:151)
at org.gradle.internal.IoActions$TextFileWriterIoAction.execute(IoActions.java:127)
at org.gradle.internal.IoActions.writeTextFile(IoActions.java:45)
at org.gradle.reporting.HtmlReportRenderer$DefaultHtmlReportContext.renderHtmlPage(HtmlReportRenderer.java:118)
at org.gradle.api.internal.tasks.testing.report.DefaultTestReport$HtmlReportFileGenerator.run(DefaultTestReport.java:147)
at org.gradle.internal.operations.DefaultBuildOperationExecutor$RunnableBuildOperationWorker.execute(DefaultBuildOperationExecutor.java:300)
at org.gradle.internal.operations.DefaultBuildOperationExecutor$RunnableBuildOperationWorker.execute(DefaultBuildOperationExecutor.java:292)
at org.gradle.internal.operations.DefaultBuildOperationExecutor.execute(DefaultBuildOperationExecutor.java:174)
at org.gradle.internal.operations.DefaultBuildOperationExecutor.access0(DefaultBuildOperationExecutor.java:48)
at org.gradle.internal.operations.DefaultBuildOperationExecutor$ParentPreservingQueueWorker.execute(DefaultBuildOperationExecutor.java:342)
at org.gradle.internal.operations.DefaultBuildOperationQueue$WorkerRunnable.runOperation(DefaultBuildOperationQueue.java:230)
at org.gradle.internal.operations.DefaultBuildOperationQueue$WorkerRunnable.access0(DefaultBuildOperationQueue.java:172)
at org.gradle.internal.operations.DefaultBuildOperationQueue$WorkerRunnable.call(DefaultBuildOperationQueue.java:209)
at org.gradle.internal.operations.DefaultBuildOperationQueue$WorkerRunnable.call(DefaultBuildOperationQueue.java:203)
at org.gradle.internal.work.DefaultWorkerLeaseService.withLocks(DefaultWorkerLeaseService.java:154)
at org.gradle.internal.operations.DefaultBuildOperationQueue$WorkerRunnable.runBatch(DefaultBuildOperationQueue.java:203)
at org.gradle.internal.operations.DefaultBuildOperationQueue$WorkerRunnable.run(DefaultBuildOperationQueue.java:177)
... 3 more
Caused by: java.io.IOException: Unable to create directory 'C:\xxx\project\project-test\build\reports\tests\test\packages\| \test\testxml.xml | test_topic | EVENT_TYPE | \result'
at org.gradle.internal.IoActions$TextFileWriterIoAction.execute(IoActions.java:141)
... 19 more
有人知道如何解决这个问题吗?我唯一能想到的 'solution' 是禁用报告,这有效,但更像是一种变通方法而不是解决方案。为了禁用,我在 gradle.build 中为此使用了以下配置:
apply plugin: 'java'
apply plugin: 'groovy'
test {
reports {
junitXml.enabled = false
html.enabled = false
}
}
(灵感来自:How to make Gradle build produce HTML test report instead of XML default?)
根据提供的信息,它似乎正在尝试创建一个名为:
的目录
'C:\xxx\project\project-test\build\reports\tests\test\packages\| \test\testxml.xml | test_topic | EVENT_TYPE | \result'
你能展示一下传入 messagePath
的代码吗?我怀疑你传递的是整行数据而不仅仅是 messagePath
(我会大胆猜测你正在对数组执行 .toString() 而不是传递第一个元素数组)
我终于找到了罪魁祸首。显然,这些文件名对应于 JUnit 生成 Cucumber 测试报告的默认行为。在 *NIX 上,这没有任何问题。然而,在 Windows 上,由于 Examples
中的管道,这将导致异常。 IOException
显然有些特殊,因为我在互联网上发现的最多例外是 FileNotFoundException
。这解释了为什么我花了这么长时间才找到答案,我专注于异常。
这里的解决方案是在 运行 Cucumber 测试时使用以下 JUnitOption
作为 @CucumberOptions
注释:--filename-compatible-names
.
Java 和 Spring 的代码示例如下所示:
@RunWith(Cucumber.class)
@CucumberOptions(junit = {"--filename-compatible-names"})
public class CucumberRunner {
}
如果这些不间断的 OS 依赖选项是默认的而不是可选的,那就太好了。
我正在开发一个项目,该项目结合使用了 Windows、Java、Groovy、Gradle 和 Cucumber。这种组合在我的 Windows 机器上给我带来了一些我的 *NIX 同事没有遇到的问题。 运行 gradle 构建后,gradle 想要输出一些报告。这些报告的位置和文件名显然是由 Cucumber 测试的定义或输出决定的。不幸的是,所使用的名称不能用作文件名,因此每个测试报告都会出现 IOException。
对于 Cucumber 测试,我们使用以下结构:
Scenario Outline: Receive and parse ReturnItem from Service
Given The message from service return item outlined in <messagePath>
When We process the message
Then XXX posted a message to YYY on topic <topic> with event <eventType>
And payload matches <resultPath>
| messagePath | topic | eventType | resultPath |
| /test/testxml.xml | test_topic | EVENT_TYPE | /result/result.json |
在 运行 之后,我收到以下异常:
Caused by: org.gradle.api.UncheckedIOException: Could not write to file 'C:\xxx\project\build\reports\tests\test\packages\| \test\testxml.xml | test_topic | EVENT_TYPE | \result\result.html'.
at org.gradle.internal.IoActions$TextFileWriterIoAction.execute(IoActions.java:151)
at org.gradle.internal.IoActions$TextFileWriterIoAction.execute(IoActions.java:127)
at org.gradle.internal.IoActions.writeTextFile(IoActions.java:45)
at org.gradle.reporting.HtmlReportRenderer$DefaultHtmlReportContext.renderHtmlPage(HtmlReportRenderer.java:118)
at org.gradle.api.internal.tasks.testing.report.DefaultTestReport$HtmlReportFileGenerator.run(DefaultTestReport.java:147)
at org.gradle.internal.operations.DefaultBuildOperationExecutor$RunnableBuildOperationWorker.execute(DefaultBuildOperationExecutor.java:300)
at org.gradle.internal.operations.DefaultBuildOperationExecutor$RunnableBuildOperationWorker.execute(DefaultBuildOperationExecutor.java:292)
at org.gradle.internal.operations.DefaultBuildOperationExecutor.execute(DefaultBuildOperationExecutor.java:174)
at org.gradle.internal.operations.DefaultBuildOperationExecutor.access0(DefaultBuildOperationExecutor.java:48)
at org.gradle.internal.operations.DefaultBuildOperationExecutor$ParentPreservingQueueWorker.execute(DefaultBuildOperationExecutor.java:342)
at org.gradle.internal.operations.DefaultBuildOperationQueue$WorkerRunnable.runOperation(DefaultBuildOperationQueue.java:230)
at org.gradle.internal.operations.DefaultBuildOperationQueue$WorkerRunnable.access0(DefaultBuildOperationQueue.java:172)
at org.gradle.internal.operations.DefaultBuildOperationQueue$WorkerRunnable.call(DefaultBuildOperationQueue.java:209)
at org.gradle.internal.operations.DefaultBuildOperationQueue$WorkerRunnable.call(DefaultBuildOperationQueue.java:203)
at org.gradle.internal.work.DefaultWorkerLeaseService.withLocks(DefaultWorkerLeaseService.java:154)
at org.gradle.internal.operations.DefaultBuildOperationQueue$WorkerRunnable.runBatch(DefaultBuildOperationQueue.java:203)
at org.gradle.internal.operations.DefaultBuildOperationQueue$WorkerRunnable.run(DefaultBuildOperationQueue.java:177)
... 3 more
Caused by: java.io.IOException: Unable to create directory 'C:\xxx\project\project-test\build\reports\tests\test\packages\| \test\testxml.xml | test_topic | EVENT_TYPE | \result'
at org.gradle.internal.IoActions$TextFileWriterIoAction.execute(IoActions.java:141)
... 19 more
有人知道如何解决这个问题吗?我唯一能想到的 'solution' 是禁用报告,这有效,但更像是一种变通方法而不是解决方案。为了禁用,我在 gradle.build 中为此使用了以下配置:
apply plugin: 'java'
apply plugin: 'groovy'
test {
reports {
junitXml.enabled = false
html.enabled = false
}
}
(灵感来自:How to make Gradle build produce HTML test report instead of XML default?)
根据提供的信息,它似乎正在尝试创建一个名为:
的目录'C:\xxx\project\project-test\build\reports\tests\test\packages\| \test\testxml.xml | test_topic | EVENT_TYPE | \result'
你能展示一下传入 messagePath
的代码吗?我怀疑你传递的是整行数据而不仅仅是 messagePath
(我会大胆猜测你正在对数组执行 .toString() 而不是传递第一个元素数组)
我终于找到了罪魁祸首。显然,这些文件名对应于 JUnit 生成 Cucumber 测试报告的默认行为。在 *NIX 上,这没有任何问题。然而,在 Windows 上,由于 Examples
中的管道,这将导致异常。 IOException
显然有些特殊,因为我在互联网上发现的最多例外是 FileNotFoundException
。这解释了为什么我花了这么长时间才找到答案,我专注于异常。
这里的解决方案是在 运行 Cucumber 测试时使用以下 JUnitOption
作为 @CucumberOptions
注释:--filename-compatible-names
.
Java 和 Spring 的代码示例如下所示:
@RunWith(Cucumber.class)
@CucumberOptions(junit = {"--filename-compatible-names"})
public class CucumberRunner {
}
如果这些不间断的 OS 依赖选项是默认的而不是可选的,那就太好了。