我在我的项目中使用 TestNG 和 Cucumber。
使用过的版本:
<dependency>
<groupId>org.testng</groupId>
<artifactId>testng</artifactId>
<version>7.4.0</version>
</dependency>
<dependency>
<groupId>io.cucumber</groupId>
<artifactId>cucumber-testng</artifactId>
<version>7.0.0</version>
</dependency>
<dependency>
<groupId>io.cucumber</groupId>
<artifactId>cucumber-java</artifactId>
<version>7.0.0</version>
</dependency>
一切正常,但我需要在测试运行开始之前进行一些动态标签操作。 更具体地说 - 我需要根据某些环境条件添加额外的过滤标签表达式。
当前的实现是带有
AbstractTestNGCucumberTests
字段的 TestNGCucumberRunner
类。
我需要更改/添加一些代码行的地方是在
TestNGCucumberRunner
类的构造函数中,因为运行程序就在那里初始化并开始测试运行。
问题是 cucumber-testng 依赖项中的几乎所有类都不是
public
和 final
。所以我无法扩展类并覆盖一些逻辑。
我看到的唯一方法是复制依赖于我的源文件夹的所有类,这是一个奇怪而愚蠢的想法。
有什么建议可以让我实现我的目标吗?
扩展
AbstractTestNGCucumberTests
时,您可以过滤 scenarios()
的输出
public class RunCucumberTest extends AbstractTestNGCucumberTests {
@DataProvider(parallel = true)
@Override
public Object[][] scenarios() {
Object[][] scenarios = super.scenarios();
// Do filtering here
return scenarios;
}
}
由于数据提供程序用于调用测试方法,因此您可以安全地将第一个数组元素转换为
PickleWrapper
并使用 pickleWrapper.getPickle().get tags()
访问标签。
上面这个解决方案非常好。它让我走上了正确的道路。我不明白如何在运行时覆盖标签。但我希望整个过滤工作与黄瓜标签的常见“和”“或”“非”表达式一起工作,并且也像传递用逗号分隔的多个标签一样简单。
因此,在从 AbstractTestNGCucumberTests 开始挖掘黄瓜类一整天后,我了解了标签的具体处理方式。然后,我找到了完美的解决方案。这是完整的代码。
/**
* This runner is a hybrid runner which can run normally as local runner with Cucumber Options or run with tags variable passed from Pipeline tools or from any other sources
* <br></br>
* This runner works with either of them or both combined. Let's say You have passed '@smoke' tag in @CucumberOptions annotation which have 100 scenarios, then additionally you can also pass a runtime tag "@Login" and filter again.
*/
@CucumberOptions( features = "src/test/resources/features/",
glue = { "stepDefinitions", "hooks" },
plugin = { "pretty", "com.aventstack.extentreports.cucumber.adapter.ExtentCucumberAdapter:" },
tags = "" ) //Pass tags here as usual
public class CucumberRunnerTest extends AbstractTestNGCucumberTests
{
@DataProvider
@Override
public Object[][] scenarios()
{
Object[][] scenarios = super.scenarios();
String dynamicTags = System.getenv("tags"); //passed from Pipeline
//Or add any other sources you want to get the tags from
if ( dynamicTags != null && !dynamicTags.equals("") ) return (Arrays.stream(scenarios).filter(scenario -> TagExpressionParser.parse(dynamicTags).evaluate((( PickleWrapper ) scenario[0]).getPickle().getTags())).collect(Collectors.toList())).toArray(new Object[0][0]);
else return scenarios;
}
}
我将其范围缩小到一行简单的 TagExpression,但我花了几个小时才找到这些并理解这么多不同的类。
尝试一次,希望有帮助。