I've written a very simple wrapper around the JUnit5 platform to run tests filtered by my external logics (which feeds path, packageIds, filterFilePath - handling of these was replaced by constant values in code samples to simplify the code snippets).
Here is how the main logic of this wrapper looks like:
public static void main(String[] args) throws JsonProcessingException {
String path = "D:\\repo\\cucumber-java-skeleton\\build\\libs";
String[] packageIds = "io.cucumber.skeleton".split(",");
String filterFilePath = "D:\\repo\\testrunner\\Tests\\Data\\DummyDataProject\\Java\\DummyJavaFilter.json";// contains JSON serialized list of correct test IDs
ClassLoader contextLoader = TestsLoader.GetLoader(path);
Thread.currentThread().setContextClassLoader(contextLoader);
final Launcher launcher = LauncherFactory.create();
List<TestResult> results = new ArrayList<TestResult>();
launcher.execute(getFilteredTestPlan(launcher, filterFilePath),
new TestRunnerExecutionListener(results));
ObjectMapper mapper = new ObjectMapper();
final String jsonResult = mapper.writerWithDefaultPrettyPrinter().writeValueAsString(results);
System.out.print("-==TEST RESULTS START==-");
System.out.print(jsonResult);
System.out.print("-==TEST RESULTS END==-");
}
}
This method returns the TestPlan filtered to IDs which I want to execute (this logics works fine and as expected)
static TestPlan getFilteredTestPlan(Launcher launcher, String filterFilePath) {
String json = new String(Files.readAllBytes(Paths.get(filterFilePath)));
ObjectMapper mapper = new ObjectMapper();
List<String> testIds = mapper.readValue(json, new TypeReference<List<String>>() {});
LauncherDiscoveryRequest request = LauncherDiscoveryRequestBuilder.request()
.selectors(testIds.stream().map(id -> selectUniqueId(id)).toArray(UniqueIdSelector[]::new))
.filters(includeClassNamePatterns(".*")).build();
return launcher.discover(request);
}
So the problem is, that when running this code on a perfectly fine and simple solution like this one provided by @M.P. Korstanje with some additions in gradle.build dependencies section:
testImplementation 'io.cucumber:cucumber-junit-platform-engine:' + cucumberVersion
For junit-platform integration, and these for building proper jar package with discoverable tests:
jar {
from configurations.testCompileClasspath.collect { it.isDirectory() ? it : zipTree(it) }
from sourceSets.test.output
}
The solution itself runs perfectly smooth when step definitions are added and running tests as expected (using default gradle test task). But when running using code provided above - it fails to find step definitions and fails with io.cucumber.junit.platform.engine.UndefinedStepException even though the steps are present. Adding glue property to @CucumberOptions doesn't solve the issue as well (though shouldn't even be needed as step definitions are in the same package).
So I've spent lots of time digging through all available sources without any luck for a few days already, any help will be much appreciated.
I've removed all error handling and section that handles discovery of the tests as irrelevant to the problem, test IDs coming from this code as input are verified correctly.
Update: When I am adding step definitions into a class contained in the same package which contains executor logics, it successfully discovers it, even though the glue setting points to a totally different package, it seems that these annotations are ignored, as code above discovers tests even when these annotations are removed completely:
@RunWith(Cucumber.class)
@CucumberOptions(plugin = { "pretty" }, glue = "io.cucumber.skeleton")
.