Skip to content

Conversation

@javier-espinazo
Copy link

@javier-espinazo javier-espinazo commented Oct 23, 2025

I am trying to generate snapshots as part of Cucumber scenario executions. However, Cucumber scenarios and features are not classes, so every snapshot for every scenario gets lumped into a single .snap file. By making the constructor of SnapshotFile public, I can make the library create one .snap file per feature file.

@javier-espinazo javier-espinazo marked this pull request as ready for review October 23, 2025 16:40
@javier-espinazo
Copy link
Author

This code currently works fine, wouldn't need reflection if the constructor were public:

private SnapshotFile createSnapshotFile(Scenario scenario)
                    throws InvocationTargetException, InstantiationException, IllegalAccessException {
        Constructor<SnapshotFile> constructor = (Constructor<SnapshotFile>) Arrays
                        .stream(SnapshotFile.class.getDeclaredConstructors())
                        .filter(c -> c.getParameterCount() == 3
                                        && Arrays.equals(c.getParameterTypes(),
                                                        new Class<?>[] { String.class, String.class, Class.class }))
                        .findFirst()
                        .orElseThrow(() -> new IllegalStateException(
                                        "Could not find constructor for " + SnapshotVerifier.class.getName()));

        constructor.setAccessible(true);

        final Path featureFileRelativePath = Path.of(scenario.getUri().getSchemeSpecificPart());

        final SnapshotConfig snapshotConfig = new PropertyResolvingSnapshotConfig();
        final Path snapshotDir = featureFileRelativePath.getParent().resolve(snapshotConfig.getSnapshotDir());
        final String snapshotFile = snapshotDir
                        .resolve(featureFileRelativePath.getFileName().toString().replace("feature", "snap"))
                        .toString();

        // Support legacy trailing space syntax
        String testSrcDir = snapshotConfig.getOutputDir().replace("java", "resources");
        String testSrcDirNoTrailing = testSrcDir.endsWith("/") ? testSrcDir.substring(0, testSrcDir.length() - 1)
                        : testSrcDir;

        return constructor.newInstance(testSrcDirNoTrailing, snapshotFile, this.getClass());
    }

Generates something like this:

javier-espinazo@localhost project % ls src/test/resources/acceptance/dir/subdir
__snapshots__          feature1.feature  feature2.feature
javier-espinazo@localhost project % ls src/test/resources/acceptance/dir/subdir/__snapshots__ 
feature1.snap             feature1.snap.debug       feature2.snap

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant