1

I am trying to make use of https://junit.org/junit5/docs/current/user-guide/#launcher-api-listeners-custom, created my own Listener that implements TestExecutionListener:

public class JunitTestListener implements TestExecutionListener {

    public static final Logger logger = LoggerFactory.getLogger(JunitTestListener.class);

    /**
     * Called when the execution of the {@link TestPlan} has finished,
     * <em>after</em> all tests have been executed.
     *
     * @param testPlan describes the tree of tests that have been executed
     */
    @Override
    public void testPlanExecutionFinished(TestPlan testPlan) {
        logger.info("Mutzu was here");
    }

    @Override
    public void executionFinished(TestIdentifier testIdentifier, TestExecutionResult testExecutionResult) {
        logger.info("Mutzu was here");
    }
}

I have create META-INF/services/org.junit.platform.launcher.TestExecutionListener and added there the custom listener class, however it is not called when running with Karate:

import com.intuit.karate.junit5.Karate;

class E2ETest {
    
    // this will run all *.feature files that exist in sub-directories
    // see https://github.com/intuit/karate#naming-conventions   
    @Karate.Test
    Karate testAll() {
        return Karate.run().relativeTo(getClass());
    }
    
}

Any idea on how to make it work?

Thanks!


It seems that with this ExecutionHook I can have access to after/before step/scenario/feature however I cannot control the result of a scenario made up of other scenarios. I can't possibly know in ExecutionHook what is a result of a "test", test in my acceptance meaning a scenario defined and composed with other scenarios. For example, if I have:

Background:
    * def feature1 = read('classpath:create_schema.feature')
    * def feature2 = read('classpath:create_dataset.feature')
    * def feature3 = read('classpath:create_mergepolicy.feature')

  Scenario: Some test
    Given def schema = call feature1
    And def schemaId = schema.schemaId

    Given def datasetArg = { schemaId: '#(schemaId)' }
    And def dataset = call feature2 datasetArg
    And def datasetId = dataset.datasetId

    Given def mergePolicyArg = { datasetId: '#(datasetId)' }
    And def mergePolicy = call feature3 mergePolicyArg
    And def mergePolicyId = mergePolicy.mergePolicyId

If there is a failure at some step, let's say call within feature1, then with ExecutionHook I get the failing event 2 times, one for scenario failing within feature1 and then another fail for Scenario: Some test, which is the test I run.

Any idea on how to have a single event triggered if some step fails in Scenario: Some test?

Samuel Liew
  • 76,741
  • 107
  • 159
  • 260
Marius Ioana
  • 91
  • 1
  • 2

1 Answers1

0

The Karate JUnit5 support is based on DynamicNode and is known to be not bound by the usual life-cycle. It is intended to make the developer experience better in IntelliJ and Eclipse, that's all.

Maybe you should be looking at the Karate ExecutionHook instead.

Peter Thomas
  • 54,465
  • 21
  • 84
  • 248
  • 1
    Looking on ExecutionHook, however I realised now that I was using in Intellij Cucumber runner directly created from feature file and there was no way to detect that Junit listener... Now it seems that when using Junit to run the test it detects the Junit listener however seems that indeed does not work like the usual life-cycle and probably I need to use the solution you proposed. – Marius Ioana Jul 03 '20 at 15:26
  • short answer: use ScenarioContext.callDepth to know whether you are in a "called" Scenario or not. otherwise feel free to contribute code, this is open-source after all. also I don't understand why you have to go down this route, the Results class will ultimately contain all the data you need. finally, I feel more people should just use the existing reports or JSON / XML files - or help improve them instead of going off and doing all these things and re-invent the wheel – Peter Thomas Jul 04 '20 at 13:56