【问题标题】:Cucumber UndefinedStepException when running tests with external runner based on JUnit5 platform使用基于 JUnit5 平台的外部运行器运行测试时 Cucumber UndefinedStepException
【发布时间】:2020-06-30 10:26:57
【问题描述】:

我围绕 JUnit5 平台编写了一个非常简单的包装器来运行由我的外部逻辑过滤的测试(它提供路径、packageIds、filterFilePath - 对这些的处理被代码示例中的常量值替换以简化代码 sn-ps )。

这个包装器的主要逻辑如下所示:

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==-");
    }
}

此方法返回过滤到我要执行的 ID 的 TestPlan(此逻辑工作正常且符合预期)

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);
}

所以问题是,当在 @M.P. 提供的 this one 等完美简单的解决方案上运行此代码时。 Korstanje 在 gradle.build 依赖项部分添加了一些内容:

    testImplementation 'io.cucumber:cucumber-junit-platform-engine:' + cucumberVersion

对于 junit 平台集成,以及这些用于构建具有可发现测试的适当 jar 包:

jar {
  from configurations.testCompileClasspath.collect { it.isDirectory() ? it : zipTree(it) }
  from sourceSets.test.output
}

当添加步骤定义并按预期运行测试(使用默认的 gradle 测试任务)时,解决方案本身运行非常顺利。但是,当使用上面提供的代码运行时 - 它无法找到步骤定义,并且即使存在步骤,也会出现 io.cucumber.junit.platform.engine.UndefinedStepException 失败。将粘合属性添加到 @CucumberOptions 也不能解决问题(尽管甚至不需要,因为步骤定义在同一个包中)。

所以我已经花了很多时间在所有可用资源中挖掘几天,但没有任何运气,任何帮助将不胜感激。

我已删除所有错误处理和处理与问题无关的测试发现的部分,来自此代码的测试 ID 作为输入已得到正确验证。

更新: 当我将步骤定义添加到包含执行程序逻辑的同一包中的类中时,它成功地发现它,即使胶水设置指向完全不同的包,似乎这些注释被忽略了,因为上面的代码甚至发现了测试当这些注释被完全删除时:

@RunWith(Cucumber.class)
@CucumberOptions(plugin = { "pretty" }, glue = "io.cucumber.skeleton")

.

【问题讨论】:

    标签: java cucumber junit5


    【解决方案1】:

    所以经过一些实验,我想出了一个可以解决问题的肮脏技巧:

    System.setProperty("cucumber.glue", String.join(",", packageIds));//packageIds has to contain all Step Definitions pacakges
    

    这添加了稍后由this 代码处理的系统属性,如this 文档中所述,它要么获取属性文件(我未能将其添加到 Jar 文件中,因为我对 Java 还很陌生,并且Jar 包装细节)或读取我添加的 JVM 中的系统属性。一个更成功的解决方案是从包含测试的目标包中获取这些属性,如果没有过多的搜索和一些相当大量的反射使用,我也无法做到这一点。理想的解决方案是 Cucumber Runner 和 Junit 平台之间的适当集成,该平台尚未到位,或者我以某种方式错过了它。任何更好的答复将不胜感激,并将被标记为正确答案。

    【讨论】:

      猜你喜欢
      • 2020-05-23
      • 1970-01-01
      • 2021-03-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-11-01
      相关资源
      最近更新 更多