首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何返回要从步骤定义文件执行的当前方法

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

Stack Overflow用户
提问于 2018-05-24 00:09:59
回答 1查看 1.7K关注 0票数 0

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

代码语言:javascript
复制
    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);
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2018-05-25 20:30:04

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

覆盖Runtime.java行为-

  1. 从这个链接https://github.com/cucumber/cucumber-jvm/blob/v1.2.5/core/src/main/java/cucumber/runtime/Runtime.java下载1.2.5类
  2. 在类路径中创建一个包cucumber.runtime,并在其中复制Runtime类。

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

代码语言:javascript
复制
    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行)在现有的第224行之前添加第210行。基本上,如果在干运行模式下,不要执行钩子。try块包含以下代码。if(!runtimeOptions.isDryRun()) hook.execute(scenarioResult);

CustomFormatter -现在将将所有细节存储在ThreadLocal变量中。

代码语言:javascript
复制
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()方法中的打印行注释,就可以看到输出如下所示。

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

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

在Hook将-Corresponds与Map - Map<Scenario, List<Match>> beforeHooks in CustomFormatter class匹配之前

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

Hook Matches -Corresponds to Map - Map<Scenario, List<Match>> afterHooks in CustomFormatter class

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

这是运行一个功能文件,如下所示。如果您有多个特性文件,您将在featureDetails地图中有多个特征键。钩子将被添加到钩子地图。

代码语言:javascript
复制
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对象。如果可用,可以很容易地迭代featureDetails映射并获得前钩子,然后是可用的步骤,然后是之后的钩子。用于获取钩子方法名称

ThreadLocal类-

代码语言:javascript
复制
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();
    }
}

StepHookDetails类-

代码语言:javascript
复制
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;
    }
}

检查商店中的详细信息-

您可以使用下面的代码作为示例查看地图中的详细信息并按顺序排列。第二步前

代码语言:javascript
复制
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行在钩子前第8行()步骤SampleSteps.userGetsCountFromAndStores(String) Car0 Steps SampleSteps.userGetsCountFromAndStores(String) Car1后Hook SampleSteps.afterOne(场景)场景第15行在Hook SampleSteps.before()步骤SampleSteps.userGetsCountFromAndStores(String) Car0 Steps SampleSteps.userGetsCountFromAndStores(String) Car1后Hook SampleSteps.afterOne(场景)

这也将适用于场景大纲。

更新-

代码语言:javascript
复制
Feature: UI Automation

@P1 
Scenario: Validate_Home_page 
Given the customer opens launches the homepage
代码语言:javascript
复制
@Given("^the customer opens launches the homepage$") 
    public void openbrowser() { }
代码语言:javascript
复制
public static void main (String args[]) throws IOException {

        String[] argv = new String[] { "-g", "cucumpar.test.stepdefs", "src/test/resources/features/features.feature", 
                "-t", "@P1" , "-p", "cusform.CustomFormatter","-d"}; 
        ClassLoader contextClassLoader = Thread.currentThread().getContextClassLoader(); 
        byte exitstatus = Main.run(argv, contextClassLoader);
        ----------------
        StepHookDetails sd = ThreadLocalStepHookDetails.get();
        ----------------
    }

结果

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

更新

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

代码语言:javascript
复制
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;
    }

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

代码语言:javascript
复制
ee.getValue().stream().forEach(s -> System.out.println("Steps " + s.getLocation() + " " + s.getArguments() + " " + s.getDataTableData()));

对于此特性文件

代码语言:javascript
复制
 Scenario: Scenario Four
    And car gets count
      | car  | owner      |
      | Car1 | OwnerOne   |
      | Car2 | OwnerTwo   |
      | Car3 | OwnerThree |

得到了这个输出--第一行是标题,根据需要定制。

SampleSteps.carGetsCount(DataTable)汽车,车主,Car1,OwnerOne,Car2,OwnerTwo,Car3,OwnerThree]

更新

代码语言:javascript
复制
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;
    }
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/50499130

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档