Open aslakhellesoy opened 4 years ago
Without a reproducer or some triangulation it'd say it's impossible to tell. The javadoc for FileOutputStream
is:
* @exception FileNotFoundException if the file exists but is a directory
* rather than a regular file, does not exist but cannot
* be created, or cannot be opened for any other reason
So for example do any of these paths work:
target\cucumber\cucumberReport.json
target\cucumberReport.json
cucumberReport.json
And do any of the above paths work when the file/folders already exists?
We're not doing mkdir -p
No. We are creating the parent directories:
private static FileOutputStream createFileOutputStream(File file) {
try {
File parentFile = file.getParentFile();
if (parentFile != null) {
parentFile.mkdirs();
}
return new FileOutputStream(file);
} catch (FileNotFoundException e) {
throw new IllegalArgumentException(String.format("" +
"Couldn't create a file output stream for %s.\n" +
"Make sure the the file isn't a directory.\n" +
"The details are in the stack trace below:",
file),
e);
}
}
If I am using cucumber version 5.5.0 the plugin @CucumberOptions is working fine with target\cucumber\cucumberReport.json
, it is creating cucumber directory successfully but when I update the version to 6.6.0 it starts giving me the same error.
So I simply mention json:target/cucumberReport.json
plugin option where I removed the cucumber folder then it won't give you such error.
But why it is giving such error to not allowing to create a new directory inside the target folder by just upgrading the version, don't know.
That's useful information @ITMANUPAM - hopefully it will make it easier to identify the problem. We did touch this code recently, so I would not be surprised if a regression snuck in!
I can't reproduce this on Windows 7. If someone can debug PluginFactory.createFileOutputStream
and see what is going on that would be most helpful.
However I'm guessing that mkdirs
fails for some reason. Commenting it out is the only way I can reproduce the exception. I've added a test for the case and replaced mkdirs
with Files.createDirectories
which checks for a few more edge cases. But without confirmation its a stab in the dark.
@aslakhellesoy @ITMANUPAM with v6.6.1 released, could you please try and see if that resolved the issue.
Closing this due to a lack of feedback. Feel free to reopen with more information.
I'm still facing this issue with 6.7.0
@mvalle I'm afraid that doesn't help much.
Could you debug PluginFactory.createFileOutputStream
and see what is going wrong?
Still facing this with all 6.x.x releases. Currently trying 6.8.1, and it's the same as when I tried it on 6.0.0.
@mpkorstanje I have debugged:
1) initializationError(Runner)
java.lang.IllegalArgumentException: Couldn't create parent directories of target/report/cucumber.json.
Make sure the the directory isn't a file.
The details are in the stack trace below:
at io.cucumber.core.plugin.PluginFactory.createFileOutputStream(PluginFactory.java:220)
at io.cucumber.core.plugin.PluginFactory.openStream(PluginFactory.java:198)
at io.cucumber.core.plugin.PluginFactory.convert(PluginFactory.java:165)
at io.cucumber.core.plugin.PluginFactory.instantiate(PluginFactory.java:98)
at io.cucumber.core.plugin.PluginFactory.create(PluginFactory.java:63)
at io.cucumber.core.plugin.Plugins.createPlugins(Plugins.java:32)
at io.cucumber.core.plugin.Plugins.<init>(Plugins.java:25)
at io.cucumber.junit.Cucumber.<init>(Cucumber.java:162)
... 20 trimmed
The root cause is the same as the in the original post, but I've seen various different error messages throughout trying various 6.x.x releases
Here's the reference code:
package ..;
import org.junit.BeforeClass;
import org.junit.runner.JUnitCore;
import org.junit.runner.RunWith;
import io.cucumber.junit.Cucumber;
import io.cucumber.junit.CucumberOptions;
@RunWith(Cucumber.class)
@CucumberOptions(
plugin = {"pretty", "html:target/cucumber", "json:target/report/cucumber.json", "junit:target/report/cucumber.xml"},
tags = "not @Ignore",
features = "classpath:com/package/test")
public final class ProductAcceptanceTests {
public static void main(String[] args) {
JUnitCore.main(ProductAcceptanceTests.class.getName());
}
}
In 5.x.x, the report is (correctly, and expectedly) generated target/report/ (report is a DIRECTORY) and it contains the following files: cucumber.json cucumber.xml
while target/cucumber contains formatter.js index.html jquery-3.4.1.min.js report.js style.css
In 6.x.x (and specifically 6.8.1): the generated file is target/cucumber (where cucumber is a FILE, not a DIRECTORY) This is apparently caused by a lack of "/" at the end of "html:target/cucumber". Note that in Cucumber-jvm 5.x.x, there was no such sensibility, and IMHO this sensibility shouldn't exist for the html plugin because it obviously needs to build a directory, not a file, so a lack of slash shouldn't confuse it.
Using
plugin = {"pretty", "html:target/cucumber/", "json:target/report/cucumber.json", "junit:target/report/cucumber.xml"},
appears to solve the problem
BUT THERE'S ANOTHER PROBLEM (to which I have not found a solution). As I soon as I change the directory of the html report to be the same where the junit and json reports are:
plugin = {"pretty", "html:target/report/", "json:target/report/cucumber.json", "junit:target/report/cucumber.xml"},
I get the original poster's problem:
java.lang.IllegalArgumentException: Couldn't create parent directories of target/report/cucumber.json.
Make sure the the directory isn't a file.
The details are in the stack trace below:
at io.cucumber.core.plugin.PluginFactory.createFileOutputStream(PluginFactory.java:220)
at io.cucumber.core.plugin.PluginFactory.openStream(PluginFactory.java:198)
at io.cucumber.core.plugin.PluginFactory.convert(PluginFactory.java:165)
at io.cucumber.core.plugin.PluginFactory.instantiate(PluginFactory.java:98)
at io.cucumber.core.plugin.PluginFactory.create(PluginFactory.java:63)
at io.cucumber.core.plugin.Plugins.createPlugins(Plugins.java:32)
at io.cucumber.core.plugin.Plugins.
Caused by: java.nio.file.FileAlreadyExistsException: /target/report at sun.nio.fs.UnixException.translateToIOException(UnixException.java:88) at sun.nio.fs.UnixException.rethrowAsIOException(UnixException.java:102) at sun.nio.fs.UnixException.rethrowAsIOException(UnixException.java:107) at sun.nio.fs.UnixFileSystemProvider.createDirectory(UnixFileSystemProvider.java:384) at java.nio.file.Files.createDirectory(Files.java:674) at java.nio.file.Files.createAndCheckIsDirectory(Files.java:781) at java.nio.file.Files.createDirectories(Files.java:727) at io.cucumber.core.plugin.PluginFactory.createFileOutputStream(PluginFactory.java:217) ... 28 more
So I have to stick with cucumber-jvm 5.7.0 for now.
Can you try: html:target/report/cucumber.html
. Note the extension.
yup! cucumber-jvm:6.8.1 works the above suggestion^
Now I have:
plugin = {"pretty", "html:target/report/cucumber.html", "json:target/report/cucumber.json", "junit:target/report/cucumber.xml"},
I no longer get java.lang.IllegalArgumentException: Couldn't create parent directories of target/report/cucumber.json.
It seems from 5.x.x -> 6.x.x the change for HTML report is that the html plugin now creates a single .html file, instead of 5 files (formatter.js index.html jquery-3.4.1.min.js report.js style.css). Thus it expects to create a file, not a directory with files anymore. This seems to have been the root cause of my problems with the other reports.
That's in the change log. But note that it's not the same problem as the @ITMANUPAM mentioned which involves the json plugin.
https://github.com/cucumber/cucumber-jvm/blob/main/release-notes/v6.0.0.md#improved-html-formatter
Mmh. I guess they could be related if the html plugin goed first. Shows the importance of creating an MCVE.
Hi @mpkorstanje , after upgrading Cucumber from 6.3.0 to 6.11.0, I'm facing the same issue. I'm on Mac, but our build machines are Windows machines, and both have the same issue. I can reliably reproduce it:
I've checked the file it's trying to read (/Users/erikpragt/projects/pks/rippledown/userneeds/build/run/build/test-results/junit.xml), but that file doesn't exist (yet).
This is coming from our Cucumber arguments:
val argsForCuke = listOf("--strict",
"--plugin", "junit:build/test-results/junit.xml",
"--plugin", "html:build/test-results-html/cucumber.html",
"--tags", "@${requirement}",
"--glue", "steps", "/${projectDir.path}/src/test/resources/gherkin")
If I change the above to this:
val argsForCuke = listOf("--strict",
"--plugin", "junit:build/junit.xml",
"--plugin", "html:build/cucumber.html",
"--tags", "@${requirement}",
"--glue", "steps", "/${projectDir.path}/src/test/resources/gherkin")
Then the test passes, so it seems that something doesn't work well with directory creations.
I did some more debugging, and at that line, if I do:
file.getAbsoluteFile() // /Users/erikpragt/projects/pks/rippledown/userneeds/build/run/build/test-results/junit.xml
file.getParentFile() // build/test-results
file.getParentFile().isFile() // the result is true
file.getParentFile().isDirectory() // the result is false
So, it seems that something creates this test-results
part as a file, instead of a directory.
However, when I check the directory using my terminal, I see this:
➜ build git:(PRD-4095_Upgrade_Cucumber_6.3_to_latest_version) ✗ ls -al
total 0
drwxr-xr-x 3 erikpragt staff 96 6 Oct 11:20 .
drwxr-xr-x 15 erikpragt staff 480 6 Oct 11:12 ..
drwxr-xr-x 2 erikpragt staff 64 6 Oct 11:20 test-results
➜ build git:(PRD-4095_Upgrade_Cucumber_6.3_to_latest_version) ✗ pwd
/Users/erikpragt/projects/pks/rippledown/userneeds/build/run/build
So, it seems test-results is directory after all?
Anything I can do to help debugging this issue?
I could reproduce this issue with Windows 10 Enterprise, Oracle JDK1.8.0_301, cucumber 6.8.1 and 6.11.0
When debugging the code of io.cucumber.core.plugin.PluginFactory#createFileOutputStream() as described I had these findings:
Seems that this issue could be easily fixed by using FileOutputStream(canonicalFile) in line 237.
canonicalfile and file are pointing to the same location
What was the difference between the two?
file = "target/cucumber-reports/cucumber.html" (as in @CucumberOptions) canonicalFile = "c:/users/violplayer/projects/myProject/target/cucumber-reports/cucumber.html"
The maven project folder being the current directory, they describe the same file.
That's odd.
Seems that this issue could be easily fixed by using FileOutputStream(canonicalFile) in line 237.
I don't have a windows system available to test this with. Would you be able to make this change and test it yourself?
The exception is thrown in some native code. I'll do the change, test it and create a pull request.
This issue has been automatically marked as stale because it has not had recent activity. It will be closed in two months if no further activity occurs.
Someone contacted me with the following stack trace:
Some theories what might be wrong (without having looked at the code or tried to reproduce it):
In any case we should inspect the file system more closely when an error occurs so we can provide a better error message.