[英]TestNG & Cucumber: Pass in single feature file name as parameter
I'd like to have a single testNG/Cucumber runner & single testng @Test that allows me to pass in the name of a single feature file as a testng parameter (using @Parameter) and run it. 我想要一个testNG / CucumberRunner和一个testng @Test,它允许我将单个功能文件的名称作为testng参数(使用@Parameter)传递并运行它。 I'd like a runtime solution. 我想要一个运行时解决方案。
I have a bunch of non-Cucumber tests using already written using the TestNG framework and I'd like to have the Cucumber code in there as well. 我已经使用TestNG框架编写了许多非Cucumber测试,我也想在其中使用Cucumber代码。
Has anyone come up with something clever ? 有谁想出一些聪明的东西?
Figured out how you can send custom cucumberoptions which contains the feature file name to the runner class. 弄清楚了如何将包含要素文件名的自定义黄瓜选项发送到跑步者类。 This will allow both cucumber and non-cucumber tests to be run from testng.xml . 这将允许从testng.xml运行黄瓜测试和非黄瓜测试。
Below text is based on details in "Cucumber for Java" book... 下面的文字基于“ Cucumber for Java”一书中的详细信息。
Cucumber checks if any option overrides have been provided for @CucumberOptions annotation. 黄瓜检查@CucumberOptions注释是否提供了任何选项替代。 Following are checked from top to bottom, stops after any one is found: 从上到下检查以下内容,找到任何一个后停止:
Values found in override will replace any values set except for the plugin argument. 在override中找到的值将替换除plugin参数之外的所有设置值。 Plugin argument will be appended. 插件参数将被追加。 Arguments which are not overridden will not be affected. 未覆盖的参数将不受影响。
testng.xml
<suite name="Default suite">
<test name="Cucumber Mix">
<classes>
<class name="cucumtestng.test.RunAbstractSampleTest"></class>
<class name="cucumtestng.test.NormalTest"></class>
</classes>
</test>
</suite>
@CucumberOptions(features="",glue="cucumtestng.test.stepdefs",snippets=SnippetType.CAMELCASE,
plugin={"pretty", "html:report", "json:reports.json"})
public class RunAbstractSampleTest extends AbstractTestNGCucumberTests {
}
public class NormalTest {
@Test
public void f() {
System.out.println("NORMAL TESTNG CLASS");
}
}
You can also use testng cucumber classes which do not extend AbstractTestNgCucumberTests but use composition... 您还可以使用不扩展AbstractTestNgCucumberTests而是使用composition的testng黄瓜类。
Setup Run As Configuration in eclipse as below and run... 如下所示在Eclipse中设置运行方式配置并运行...
This "setup" code does the trick. 此“设置”代码可以解决问题。 It gives me the cucumber feature I'm interested in running. 它为我提供了我感兴趣的黄瓜功能。 I will look at the other proposal as well. 我也会看看其他建议。
@Parameters({"featurename"})
@BeforeTest(alwaysRun = true)
public void setUpTest(String featureName) throws Exception {
testNGCucumberRunner = new TestNGCucumberRunner(this.getClass());
List<CucumberFeature> featureList = testNGCucumberRunner.getFeatures();
for (CucumberFeature feature : featureList){
if (featureName.equalsIgnoreCase(feature.getPath())){
runFeature = feature;
break;
}
}
}
Another technique is using reflection to modify the CucumberOptions annotation in real time before instantiating the runner (thanks to several older posts for the inspiration): 另一种技术是在实例化运行器之前,使用反射来实时修改CucumberOptions批注(这要归功于一些较早的帖子):
@Parameters({"featurePath"})
@BeforeTest(alwaysRun = true)
public void setUpTest(@Optional("src/main/java/cucumberFeatureFiles/Testcase.feature") String featurePath) throws Exception {
Class<?> testClass = this.getClass();
changeCucumberAnnotation(testClass, "features", new String [] {featurePath});
testNGCucumberRunner = new WaltersTestngCucumberRunner(testClass);
}
private static void changeCucumberAnnotation(Class<?> clazz, String key, Object newValue) throws NoSuchFieldException, SecurityException, IllegalArgumentException, IllegalAccessException{
Annotation options = clazz.getAnnotation(CucumberOptions.class); //get the CucumberOptions annotation
InvocationHandler proxyHandler = Proxy.getInvocationHandler(options); //setup handler so we can update Annotation using reflection. Basically creates a proxy for the Cucumber Options class
Field f = proxyHandler.getClass().getDeclaredField("memberValues"); //the annotaton key/values are stored in the memberValues field
f.setAccessible(true); //suppress any access issues when looking at f
Map<String, Object> memberValues = (Map<String, Object>) f.get(proxyHandler); //get the key-value map for the proxy
memberValues.remove(key); //renove the key entry...don't worry, we'll add it back
memberValues.put(key,newValue); //add the new key-value pair. The annotation is now updated.
}//end method
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.