Description
🤔 Problem Description
I'm experiencing high overhead during test discovery in projects using Cucumber-JVM with the JUnit Platform Engine. Specifically, the issue stems from repeated calls to File.getCanonicalFile() inside FileSource.
In our setup:
- 200+ feature files
- 6000+ containers
- 20,000+ test cases
Runtime: Windows 11 + FSlogix (actually that could be the main culprit for slow FS access), Java: 21
Discovery takes 60–70 seconds, primarily spent in canonical path resolution via:
✨ Proposed Solution
I like to propose a minor enhancement to JUnit's FileSource:
Add a static factory method:
/**
* Create a new {@code FileSource} from an existing instance but with a different
* {@link FilePosition}. This avoids redundant canonical path resolution.
*
* @param source the existing {@code FileSource}; must not be {@code null}
* @param filePosition the new {@code FilePosition}; may be {@code null}
* @return a new {@code FileSource} with same file and updated position
*/
public static FileSource withPosition(FileSource source, @Nullable FilePosition filePosition) {
Preconditions.notNull(source, "source must not be null");
return direct(source.file, filePosition); // new FileSource without canonicalPath call
}
This would reuse an already-canonical File from an existing FileSource, avoiding the repeated and expensive getCanonicalFile() call.
🛠️ Workarounds We've Tried
- We implemented a custom
CachingFileSource
variant to avoid repeated canonicalization. SinceFileSource
has private constructors, this required duplicating its entire implementation. With caching in place, discovery time dropped from ~60s to ~5s. - We also experimented with parallelizing feature parsing in Cucumber, which reduced overall time to ~20s, but did not address the core overhead from canonical path resolution.
🔄 Alternatives Considered
While this could be implemented on the Cucumber side, it currently requires duplicating the entire FileSource logic, unless JUnit provides extension points or additional factory methods.