Selenium 如何返回将从步骤定义文件执行的当前方法

Selenium 如何返回将从步骤定义文件执行的当前方法,selenium,cucumber,gherkin,Selenium,Cucumber,Gherkin,我需要这样做,以便在执行报告、日志记录等方法之前将所需参数传递给类,以便可以并行执行测试用例。我正在将关键字驱动的selenium框架转换为BDD Gherkin selenium框架。在关键字驱动的框架中,我从Excel中获取关键字,在执行方法之前通过Java反射将所需参数传递给类 String [] argv = new String[]{ "-g" ,"businesscomponents" ,"./Feat

我需要这样做,以便在执行报告、日志记录等方法之前将所需参数传递给类,以便可以并行执行测试用例。我正在将关键字驱动的selenium框架转换为BDD Gherkin selenium框架。在关键字驱动的框架中,我从Excel中获取关键字,在执行方法之前通过Java反射将所需参数传递给类

    String [] argv = new String[]{ 
            "-g"
            ,"businesscomponents"
            ,"./Features"
            //,"-t","@P1,@P2"
            ,"-n","Validate_login_search_using_sku_id"
            };
    ClassLoader contextClassLoader = Thread.currentThread().getContextClassLoader();
    byte exitstatus = Main.run(argv, contextClassLoader);

这比我想象的要容易得多。这只需要修改一个类(Runtime.java)的几行代码,就可以找出所有的hook和step方法。然后,它只需要在设置为true的dryrun模式下运行即可获得所有细节

重写Runtime.java行为-

public class ThreadLocalStepHookDetails {

    private static final ThreadLocal<StepHookDetails> threadStepHookDetails = new InheritableThreadLocal<StepHookDetails>();

    private ThreadLocalStepHookDetails() {
    }

    public static StepHookDetails get() {
        return threadStepHookDetails.get();
    }

    public static void set(StepHookDetails match) {
        threadStepHookDetails.set(match);
    }

    public static void remove() {
        threadStepHookDetails.remove();
    }
}
Feature: UI Automation

@P1 
Scenario: Validate_Home_page 
Given the customer opens launches the homepage
  • 从该链接下载1.2.5类

  • 在类路径中创建cucumber.runtime包,并在其中复制运行时类

  • 3.在私有方法runHooks(第209行)中,注释掉第210行和第214行

        private void runHooks(List<HookDefinition> hooks, Reporter reporter, Set<Tag> tags, boolean isBefore) {   
            //if (!runtimeOptions.isDryRun()) {
                for (HookDefinition hook : hooks) {
                    runHookIfTagsMatch(hook, reporter, tags, isBefore);
                }
            //}
        }
    
    如果在close()方法中取消对打印行的注释,则可以看到如下输出

    步骤方法匹配-对应于CustomFormatter类中的映射-
    映射特性详细信息

    {src/test/resources/features/format2.feature={gherkin.formatter.model。Scenario@38d8f54a=[cumber.runtime。StepDefinitionMatch@6236eb5f, cucumber.runtime。StepDefinitionMatch@7c1e2a9e], gherkin.formatter.model。Scenario@49e53c76=[cumber.runtime。StepDefinitionMatch@fa36558, cucumber.runtime。StepDefinitionMatch@672872e1]}}

    挂钩匹配之前-对应于CustomFormatter类中的Map-
    Map beforeHooks

    {gherkin.formatter.model。Scenario@38d8f54a=[gherkin.formatter.model。Match@32910148], gherkin.formatter.model。Scenario@49e53c76=[gherkin.formatter.model。Match@3f56875e]}

    挂钩匹配后--对应于CustomFormatter类中的Map-
    Map afterHooks

    {gherkin.formatter.model。Scenario@38d8f54a=[gherkin.formatter.model。Match@2b4bac49], gherkin.formatter.model。Scenario@49e53c76=[gherkin.formatter.model。Match@fd07cbb]}

    这适用于运行单个功能文件,如下所示。如果您有多个要素文件,则在
    featureDetails
    map中会有多个要素键。钩子将被添加到钩子贴图中

    Feature: Validating sample Two
        Background:
           Given user gets count from "Car0"
    
      @Format
      Scenario: Scenario Two
        And user gets count from "Car1"
    
      @Format
      Scenario: Scenario Two
        And user gets count from "Car1"
    
    重要-将三者结合在一起的关键是
    场景
    对象。迭代
    featureDetails
    映射并获得前钩子(如果可用),然后是可用步骤,然后是后钩子非常容易。 要获取钩子方法名称,请使用

    线程本地类-

    public class ThreadLocalStepHookDetails {
    
        private static final ThreadLocal<StepHookDetails> threadStepHookDetails = new InheritableThreadLocal<StepHookDetails>();
    
        private ThreadLocalStepHookDetails() {
        }
    
        public static StepHookDetails get() {
            return threadStepHookDetails.get();
        }
    
        public static void set(StepHookDetails match) {
            threadStepHookDetails.set(match);
        }
    
        public static void remove() {
            threadStepHookDetails.remove();
        }
    }
    
    Feature: UI Automation
    
    @P1 
    Scenario: Validate_Home_page 
    Given the customer opens launches the homepage
    
    对于上面的功能文件,我们得到了这个输出

    Hook SampleSteps.Before()步骤之前的场景行8 SampleSteps.UserGetScontFromandStores(字符串)[Car0]步骤 SampleSteps.UserGetScontFromandStores(字符串)[Car1]位于钩子之后 SampleSteps.afterOne(场景)场景行编号15挂接前 SampleSteps.before()步骤 SampleSteps.UserGetScontFromandStores(字符串)[Car0]步骤 SampleSteps.UserGetScontFromandStores(字符串)[Car1]位于钩子之后 SampleSteps.afterOne(场景)

    这也适用于场景大纲


    更新-

    public class ThreadLocalStepHookDetails {
    
        private static final ThreadLocal<StepHookDetails> threadStepHookDetails = new InheritableThreadLocal<StepHookDetails>();
    
        private ThreadLocalStepHookDetails() {
        }
    
        public static StepHookDetails get() {
            return threadStepHookDetails.get();
        }
    
        public static void set(StepHookDetails match) {
            threadStepHookDetails.set(match);
        }
    
        public static void remove() {
            threadStepHookDetails.remove();
        }
    }
    
    Feature: UI Automation
    
    @P1 
    Scenario: Validate_Home_page 
    Given the customer opens launches the homepage
    


    结果

    {src/test/resources/features/features.feature={gherkin.formatter.model。Scenario@6771beb3=[cumber.runtime。StepDefinitionMatch@51399530]}} {gherkin.formatter.model。Scenario@6771beb3=[]} {gherkin.formatter.model。Scenario@6771beb3=[]} 场景行4 步骤SampleSteps.openbrowser()[]


    已更新

    需要向StepDefinitionMatch类添加一些代码。与u为Runtime.java所做的类似,请在-,下载1.2.5类。将此类复制到现有cucumber.runtime包。 然后添加以下方法--

    对于此功能文件

     Scenario: Scenario Four
        And car gets count
          | car  | owner      |
          | Car1 | OwnerOne   |
          | Car2 | OwnerTwo   |
          | Car3 | OwnerThree |
    
    获得此输出-第一行是标题,根据需要自定义

    SampleSteps.cargetscont(数据表)[[car,owner],[Car1, 拥有者],[Car2,拥有者二],[Car3,拥有者三]]


    更新

    public Map<String, List<String>> getDataTableData() {
    
            Map<String, List<String>> mapData = new HashMap<>();
            if(step.getRows()!=null) {
                List<List<String>> data = new ArrayList<>();
                step.getRows().forEach(row -> data.add(row.getCells()));
                List<String> keys = data.remove(0);         
                data.stream().forEach(row -> IntStream.range(0, keys.size()).forEach(index -> {
                    List<String> tempList = new ArrayList<>();
                    tempList.add(row.get(index));
                    mapData.compute(keys.get(index), (key, val) -> {
                        if(val==null)
                            return tempList;
                        val.addAll(tempList);
                        return val;
                    });             
                }));            
            }
            return mapData;
        }
    
    公共地图getDataTableData(){ Map mapData=new HashMap(); if(step.getRows()!=null){ 列表数据=新的ArrayList(); step.getRows().forEach(row->data.add(row.getCells()); 列表键=数据。删除(0); data.stream().forEach(行->IntStream.range(0,keys.size()).forEach(索引->{ List templast=new ArrayList(); add(row.get(index)); mapData.compute(key.get(index),(key,val)->{ if(val==null) 返回圣殿骑士; 瓦尔·阿德尔(圣殿骑士); 返回val; }); })); } 返回地图数据; }
    也许这会有所帮助-感谢@Grasshopper查看并分享详细信息。我确实看了一遍,还有一个问题。我没有使用Junit runner,也没有在main方法中使用普通的java代码来调用。如何在代码中添加“cusform.CustomFormatter”?另外,我没有看到像match.getmethodname这样的选项来获取方法名,这样我就可以通过Java反射来传递必要的参数。您可以使用-p选项来传递argv数组中的自定义格式化程序。参考本文。要在Cucumber 1.2.5中获取方法名称,请使用match.getLocation()将class.method(args)作为字符串获取。在Cucumber 2中,使用getCodeLocation()获得相同的结果。我得到了类似于以下示例步骤的内容。UserGetScoutFromandStores(字符串)非常感谢您的努力和帮助。我尝试了您告诉我的所有步骤,但得到了以下结果:{mytest_1.feature={gherkin.formatter.model。Scenario@a072f6=[cumber.runtime。StepDefinitionMatch@c07d28]}}{gherkin.formatter.model。Scenario@a0
    ee.getValue().stream().forEach(s -> System.out.println("Steps " + s.getLocation() + " " + s.getArguments() + " " + s.getDataTableData()));
    
     Scenario: Scenario Four
        And car gets count
          | car  | owner      |
          | Car1 | OwnerOne   |
          | Car2 | OwnerTwo   |
          | Car3 | OwnerThree |
    
    public Map<String, List<String>> getDataTableData() {
    
            Map<String, List<String>> mapData = new HashMap<>();
            if(step.getRows()!=null) {
                List<List<String>> data = new ArrayList<>();
                step.getRows().forEach(row -> data.add(row.getCells()));
                List<String> keys = data.remove(0);         
                data.stream().forEach(row -> IntStream.range(0, keys.size()).forEach(index -> {
                    List<String> tempList = new ArrayList<>();
                    tempList.add(row.get(index));
                    mapData.compute(keys.get(index), (key, val) -> {
                        if(val==null)
                            return tempList;
                        val.addAll(tempList);
                        return val;
                    });             
                }));            
            }
            return mapData;
        }