Java 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

我希望有一个单一的testNG/Cucumber runner&single testNG@Test,它允许我将单个功能文件的名称作为testNG参数传递(使用@parameter)并运行它。我想要一个运行时解决方案

我有一堆非Cucumber测试,使用已经使用TestNG框架编写的测试,我也希望有Cucumber代码


有人想出了聪明的办法吗?

找到了如何将包含功能文件名的自定义cucumberoptions发送给runner类的方法。这将允许cucumber和非cucucumber测试从testng.xml运行

下面的文字是基于“Cumber for Java”一书中的细节


Cucumber检查是否为@CucumberOptions注释提供了任何选项覆盖。从上到下检查以下各项,发现任何一项后停止:

  • 操作系统环境变量“U”选项
  • Java系统属性cumber.options
  • 带有cucumber.options属性的Java资源包cucumber.properties
  • 在override中找到的值将替换除plugin参数外的任何值集。插件参数将被追加。未被重写的参数将不受影响


    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