Java TestNG&;Cucumber:传入单个要素文件名作为参数
我希望有一个单一的testNG/Cucumber runner&single testNG@Test,它允许我将单个功能文件的名称作为testNG参数传递(使用@parameter)并运行它。我想要一个运行时解决方案 我有一堆非Cucumber测试,使用已经使用TestNG框架编写的测试,我也希望有Cucumber代码Java TestNG&;Cucumber:传入单个要素文件名作为参数,java,cucumber,testng,Java,Cucumber,Testng,我希望有一个单一的testNG/Cucumber runner&single testNG@Test,它允许我将单个功能文件的名称作为testNG参数传递(使用@parameter)并运行它。我想要一个运行时解决方案 我有一堆非Cucumber测试,使用已经使用TestNG框架编写的测试,我也希望有Cucumber代码 有人想出了聪明的办法吗?找到了如何将包含功能文件名的自定义cucumberoptions发送给runner类的方法。这将允许cucumber和非cucucumber测试从test
有人想出了聪明的办法吗?找到了如何将包含功能文件名的自定义cucumberoptions发送给runner类的方法。这将允许cucumber和非cucucumber测试从testng.xml运行 下面的文字是基于“Cumber for Java”一书中的细节
Cucumber检查是否为@CucumberOptions注释提供了任何选项覆盖。从上到下检查以下各项,发现任何一项后停止:
testng.xml
@CucumberOptions(features=”“,glue=“cucumtestng.test.stepdefs”,snippets=SnippetType.CAMELCASE,
plugin={“pretty”、“html:report”、“json:reports.json”})
公共类RunAbstractSampleTest扩展了AbstractTestNGCucumberTests{
}
公共类正态检验{
@试验
公共空间f(){
System.out.println(“正常测试类”);
}
}
您还可以使用testng cucumber类,这些类不扩展AbstractTestNgCucumberTests,而是使用composition
安装程序在eclipse中以配置方式运行,如下所示,然后运行。。。
此“设置”代码起作用。它给了我跑步的乐趣。我亦会研究另一项建议
@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;
}
}
}
@参数({“featurename”})
@测试前(alwaysRun=true)
public void setUpTest(字符串featureName)引发异常{
testNGCucumberRunner=新的testNGCucumberRunner(this.getClass());
List featureList=testNGCucumberRunner.getFeatures();
用于(黄瓜特征:特征列表){
if(featureName.equalsIgnoreCase(feature.getPath())){
运行特性=特性;
打破
}
}
}
另一种技术是在实例化runner之前使用反射实时修改CucumberOptions注释(多亏了几篇老文章的灵感):
@参数({“featurePath”})
@测试前(alwaysRun=true)
public void setUpTest(@Optional(“src/main/java/cucumberFeatureFiles/Testcase.feature”)字符串featurePath)引发异常{
类testClass=this.getClass();
ChangeCumberAnnotation(testClass,“features”,新字符串[]{featurePath});
testNGCucumberRunner=新WaltersTestngCucumberRunner(testClass);
}
私有静态void changeCumberAnnotation(类clazz、字符串键、对象newValue)抛出NoSuchFieldException、SecurityException、IllegalArgumentException、IllegalAccessException{
Annotation options=clazz.getAnnotation(CucumberOptions.class);//获取CucumberOptions注释
InvocationHandler proxyHandler=Proxy.getInvocationHandler(options);//设置处理程序,以便我们可以使用反射更新注释。基本上为Cucumber options类创建代理
字段f=proxyHandler.getClass().getDeclaredField(“memberValues”);//注释项/值存储在memberValues字段中
f、 setAccessible(true);//查看f时禁止任何访问问题
Map memberValues=(Map)f.get(proxyHandler);//获取代理的键值映射
memberValues.remove(key);//重新保存密钥项…别担心,我们会将其添加回
memberValues.put(key,newValue);//添加新的键值对。注释现在已更新。
}//结束方法
您在使用maven吗?maven是我们正在考虑的候选产品,但我更喜欢不依赖特定构建系统的解决方案。我一直在研究Cuccumber的Java源代码,可能已经找到了一种实现这一点的方法。使用TestNGCucumberRunner的v1.2.4,我可以访问CucumberFeature对象的列表。我可以扫描列表并查找与使用testng参数输入的字符串具有相同“路径”的功能。然后,我可以使用runcumber方法将匹配功能用于跑步者。至少这是理论:-)。我要试试。这是一个在TestNGCucumberRunner中更改getFeatures()实现的选项。有一条简单的出路。调用runner类时,可以覆盖cucumberoptions标记。请参阅“覆盖选项”一节。Maven提供了传递此参数的简单方法。在testng.xml中也应该有一种方法来传递它。
@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;
}
}
}
@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