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

pvabu6sv  于 2022-11-24  发布在  其他
关注(0)|答案(1)|浏览(162)

我需要这个,这样我就可以在执行报告、日志等方法之前将所需的参数传递给类,这样测试用例就可以并行执行。我正在将我的关键字驱动 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);
f0brbegy

f0brbegy1#

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

覆盖Runtime.java行为-

1.通过此链接下载1.2.5类https://github.com/cucumber/cucumber-jvm/blob/v1.2.5/core/src/main/java/cucumber/runtime/Runtime.java
1.在类路径中创建一个包cubber.runtime,并在其中复制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);
            }
        //}
    }

1.在私有方法runHookIfTagsMatch(第217行)中,将第210行添加到现有的第224行之前。基本上,如果处于空运行模式,则不执行挂钩。try块包含此代码。if(!runtimeOptions.isDryRun()) hook.execute(scenarioResult);

**CustomFormatter -**这将在ThreadLocal变量中存储所有详细信息。

public class CustomFormatter implements Reporter, Formatter {

    private Map<String, Map<Scenario, List<StepDefinitionMatch>>> featureDetails;

    private Map<Scenario, List<StepDefinitionMatch>> scenarioDetails;

    private List<StepDefinitionMatch> stepDetails;

    private String featureUri = "";

    private Scenario scenario;

    private Map<Scenario, List<Match>> beforeHooks;

    private Map<Scenario, List<Match>> afterHooks;

    private List<Match> beforeMatches;

    private List<Match> afterMatches;

    public CustomFormatter() {
        featureDetails = new LinkedHashMap<>(); 

        beforeHooks = new LinkedHashMap<>();
        afterHooks = new LinkedHashMap<>();
    }

    @Override
    public void before(Match match, Result result) {
        beforeMatches.add(match);
    }

    @Override
    public void result(Result result) {

    }

    @Override
    public void after(Match match, Result result) {
        afterMatches.add(match);
    }

    @Override
    public void match(Match match) {
        //ThreadLocalStepDefinitionMatch.set((StepDefinitionMatch) match);
        stepDetails.add((StepDefinitionMatch) match);
    }

    @Override
    public void embedding(String mimeType, byte[] data) {
    }

    @Override
    public void write(String text) {
    }

    @Override
    public void syntaxError(String state, String event,
            List<String> legalEvents, String uri, Integer line) {
    }

    @Override
    public void uri(String uri) {
        featureUri = uri;
    }

    @Override
    public void feature(Feature feature) {
        scenarioDetails = new LinkedHashMap<>();
    }

    @Override
    public void scenarioOutline(ScenarioOutline scenarioOutline) {
    }

    @Override
    public void examples(Examples examples) {
    }

    @Override
    public void startOfScenarioLifeCycle(Scenario scenario) {

        this.scenario = scenario;

        stepDetails = new ArrayList<>();
        beforeMatches = new ArrayList<>();
        afterMatches = new ArrayList<>();
    }

    @Override
    public void background(Background background) {
    }

    @Override
    public void scenario(Scenario scenario) {
    }

    @Override
    public void step(Step step) {
    }

    @Override
    public void endOfScenarioLifeCycle(Scenario scenario) {

        scenarioDetails.put(this.scenario, stepDetails);
        beforeHooks.put(this.scenario, beforeMatches);
        afterHooks.put(this.scenario, afterMatches);
    }

    @Override
    public void done() {
    }

    @Override
    public void close() {
        /*System.out.println(featureDetails);
        System.out.println(beforeHooks);
        System.out.println(afterHooks);*/

        StepHookDetails shd = new StepHookDetails(featureDetails, beforeHooks, afterHooks);
        ThreadLocalStepHookDetails.set(shd);
    }

    @Override
    public void eof() {
        featureDetails.put(featureUri, scenarioDetails);
    }
}

如果在close()方法中取消注解打印行,您可以看到如下输出。

  • 步骤方法匹配 * -对应于Map-Map<String, Map<Scenario, List<StepDefinitionMatch>>> featureDetails in CustomFormatter class

{src/test/resources/features/format2.features ={ cucumber 格式器.模型.场景@38d8f54a =[ cucumber .运行时.步骤定义匹配@6236eb5f, cucumber .运行时.步骤定义匹配@7c1e2a9e], cucumber 格式器.模型.场景@49e53c76 =[ cucumber .运行时.步骤定义匹配@fa36558, cucumber .运行时.步骤定义匹配@672872e1]}}

  • 挂钩匹配之前 * -对应于Map-Map<Scenario, List<Match>> beforeHooks in CustomFormatter class

这是一个很好的例子。

  • 挂接匹配后 * - -对应于Map-Map<Scenario, List<Match>> afterHooks in CustomFormatter class

这是一个很好的例子。
这是为了运行一个单一的功能文件,如下所示。如果你有多个功能文件,你将有多个功能键在featureDetailsMap。挂钩将被添加到挂钩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"

重要说明-将这三个函数绑定在一起的关键是Scenario对象。迭代featureDetailsMap并获取before hook(如果可用)、available steps和after hook非常简单。要获取hook方法名,请使用
线程本地类-

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();
    }
}

挂钩详细信息类-

public class StepHookDetails {

    private Map<String, Map<Scenario, List<StepDefinitionMatch>>> featureDetails;

    private Map<Scenario, List<Match>> beforeHooks;

    private Map<Scenario, List<Match>> afterHooks;

    public StepHookDetails() {}

    public StepHookDetails(
            Map<String, Map<Scenario, List<StepDefinitionMatch>>> featureDetails,
            Map<Scenario, List<Match>> beforeHooks,
            Map<Scenario, List<Match>> afterHooks) {
        this.featureDetails = featureDetails;
        this.beforeHooks = beforeHooks;
        this.afterHooks = afterHooks;
    }

    public Map<String, Map<Scenario, List<StepDefinitionMatch>>> getFeatureDetails() {
        return featureDetails;
    }

    public void setFeatureDetails(
            Map<String, Map<Scenario, List<StepDefinitionMatch>>> featureDetails) {
        this.featureDetails = featureDetails;
    }

    public Map<Scenario, List<Match>> getBeforeHooks() {
        return beforeHooks;
    }

    public void setBeforeHooks(Map<Scenario, List<Match>> beforeHooks) {
        this.beforeHooks = beforeHooks;
    }

    public Map<Scenario, List<Match>> getAfterHooks() {
        return afterHooks;
    }

    public void setAfterHooks(Map<Scenario, List<Match>> afterHooks) {
        this.afterHooks = afterHooks;
    }
}

在商店中查看详细信息-

你可以使用下面的代码作为一个例子来查看Map里面的细节,并在order. ie before steps after.

StepHookDetails sd = ThreadLocalStepHookDetails.get();

        sd.getFeatureDetails().entrySet().stream().forEach(
                e -> e.getValue().entrySet().stream().forEach(
                        ee -> {
                            System.out.println(ee.getKey().getLine());
                            sd.getBeforeHooks().get(ee.getKey()).stream().forEach(bh -> System.out.println(bh.getLocation()));
                            ee.getValue().stream().forEach(s -> System.out.println(s.getLocation() + " " + s.getArguments()));
                            sd.getAfterHooks().get(ee.getKey()).stream().forEach(ah -> System.out.println(ah.getLocation()));
                        }));

对于上面的特性文件得到了这个输出
方案行号8 Before Hook SampleSteps.before()Steps SampleSteps.userGetsCountFromAndStores(字符串)[Car 0] Steps SampleSteps.userGetsCountFromAndStores(字符串)[Car 1] After Hook SampleSteps.afterOne(方案)方案行号15 Before Hook SampleSteps.before()Steps SampleSteps. userGetsCountFromAndStores(字符串)[Car 0] Steps SampleSteps. userGetsCountFromAndStores(字符串)[Car 1] After Hook SampleSteps.afterOne(方案)方案行号15 Before Hook SampleSteps. before()Steps SampleSteps. userGet
这也适用于方案大纲。

已更新-

第一个
结果
{src/test/resources/features/features. features ={服务器.格式化器.模型.场景@6771beb3 =[运行时.步骤定义匹配@51399530]}} {服务器.格式化器.模型.场景@6771beb3 =[]} {服务器.格式化器.模型.场景@6771beb3 =[]}场景行号4步骤示例步骤.openbrowser()[]

已更新

需要向StepDefinitionMatch类添加一些代码。类似于您对www.example.com所做的Runtime.java下载1.2.5类,位置为-https://github.com/cucumber/cucumber-jvm/blob/v1.2.5/core/src/main/java/cucumber/runtime/StepDefinitionMatch.java。将该类复制到现有的cubber.runtime包中。然后添加以下方法--

public List<List<String>> getDataTableData() {

        List<List<String>> data = new ArrayList<>();
        if(step.getRows()!=null)
            step.getRows().forEach(row -> data.add(row.getCells()));
        return data;
    }

就是这样。在现有的print方法中调用此方法,如下所示。

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 |

获得此输出-第一行是标题,根据需要自定义。
[[汽车,所有者],[汽车1,所有者1],[汽车2,所有者2],[汽车3,所有者3]]

更新

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;
    }

相关问题