Search code examples
javacucumbercucumber-jvmcucumber-javacucumber-junit

Cucumber Java: How to force JSON plugin generation


Overview: There are instances where in I want to stop the running cucumber test pack midway -- say for example when x number of tests failed.

I can do this just fine but I want the json file (plugin = {json:...}) to be generated when the test stops. Is this doable?

What I've tried so far:

  • Debug and see where the reporting / plugin generation happens. It seems to be when this line executes:

    Cucumber.java: runtime.getEventBus().send.....
    
        @Override
        protected Statement childrenInvoker(RunNotifier notifier) {
            final Statement features = super.childrenInvoker(notifier);
            return new Statement() {
                @Override
                public void evaluate() throws Throwable {
                    features.evaluate();
                    runtime.getEventBus().send(new TestRunFinished(runtime.getEventBus().getTime()));
                    runtime.printSummary();
                }
            };
        }
    

    I was hoping to access the runtime field but it has a private modifier. I also tried accessing it via reflections but I'm not exactly getting what I need.


  • Solution

  • Found a quite dirty, but working solution and got what I need. Posting my solution here in case anyone might need.

  • Create a custom cucumber runner implementation to take the runtime instance.

    public final class Foo extends Cucumber {
        static Runtime runtime;
    
        /**
         * Constructor called by JUnit.
         *
         * @param clazz the class with the @RunWith annotation.
         * @throws IOException         if there is a problem
         * @throws InitializationError if there is another problem
         */
        public Foo(Class clazz) throws InitializationError, IOException {
            super(clazz);
        }
    
        @Override
        protected Runtime createRuntime(ResourceLoader resourceLoader, ClassLoader classLoader, RuntimeOptions runtimeOptions) throws InitializationError, IOException {
            runtime = super.createRuntime(resourceLoader, classLoader, runtimeOptions);
            return runtime;
        }
    }
    

  • Call the same line that generates the file depending on the plugin used:

    public final class ParentHook {
    
        @Before
        public void beforeScenario(Scenario myScenario) {
    
        }
    
        @After
        public void afterScenario() {
            if (your condition to stop the test) {
               //custom handle to stop the test
               myHandler.pleaseStop();
               Foo.runtime.getEventBus().send(new TestRunFinished(Foo.runtime.getEventBus().getTime()));
            }
        }
    }
    

  • This will however require you to run your test via Foo.class eg: @RunWith(Foo.class) instead of @RunWith(Cucumber.class)

    Not so much value here but it fits what I need at the moment. I hope Cucumber provides a way to do this out of the box. If there's a better way, please do post it here so I can accept your answer once verified.