Как вернуть текущий метод, который будет выполнен, из файла определения шага - PullRequest
0 голосов
/ 24 мая 2018

Мне это нужно, чтобы я мог передать необходимые аргументы классу перед выполнением этого метода для создания отчетов, ведения журнала и т. Д., Чтобы тестовые примеры могли выполняться параллельно.Я нахожусь в процессе преобразования моей основанной на ключевых словах инфраструктуры селена в среду селена BDD Gherkin. В управляемой ключевой среде инфраструктуре я получаю ключевые слова из 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);

1 Ответ

0 голосов
/ 25 мая 2018

Это было намного проще, чем я думал.Для этого просто потребовалось изменить пару строк одного класса (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

  2. Создайте пакет cucumber.runtime в classpath и скопируйте в него класс 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);
            }
        //}
    }
В приватном методе runHookIfTagsMatch (строка 217) добавьте строку 210 перед существующей строкой 224. В основном, если в режиме dryrun не выполнять ловушку.Блок 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);
    }
}

Если вы раскомментируете строки печати при закрытии() метод, вы можете увидеть результат примерно так.

Шаг Методы соответствия - Соответствует карте - 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.mo49. Cuc.runtime.StepDefinitionMatch@fa36558, cucumber.runtime.StepDefinitionMatch@672872e1]}}

до совпадений с крюком - соответствует карте - 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]} *

после совпадений с крюком - - соответствует карте - 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.Крючки будут добавлены к картам ловушек.

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 -

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 -

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

Проверьте детали в магазине -

Вы можете использовать приведенный ниже код в качестве образца, чтобы увидеть детали внутри карт и в порядке.т. е. перед шагами после.

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 До перехвата SampleSteps.before () Шаги SampleSteps.userGetsCountFromAndStores (String) [Car0] Шаги SampleSteps.userGetsCountFromAndStores (String) [Car1] После хука SampleSteps.afterOne (Scenario) Сценарий Строка № 15 перед хуком] After Hook SampleSteps.afterOne (Сценарий)

Это также будет работать для контуров сценария.


ОБНОВЛЕНО -

Feature: UI Automation

@P1 
Scenario: Validate_Home_page 
Given the customer opens launches the homepage

@Given("^the customer opens launches the homepage$") 
    public void openbrowser() { }

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= enjgherkin.formatter.model.Scenario@6771beb3=[cucumber.runtime.StepDefinitionMatch@51399530]}} {gherkin.formatter.model.Scenario@6771beb3= []} {gher.formatter.model.Scenario@6771beb3= []} Строка сценария № 4 Шаги SampleSteps.openbrowser () []


ОБНОВЛЕНО

Необходимо добавить некоторый код в класс StepDefinitionMatch.Аналогично тому, что вы сделали для Runtime.java, скачайте класс 1.2.5 по адресу - https://github.com/cucumber/cucumber-jvm/blob/v1.2.5/core/src/main/java/cucumber/runtime/StepDefinitionMatch.java. Скопируйте этот класс в существующий пакет cucumber.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;
    }

Вот и все.Вызовите этот метод в существующем методе печати, как показано ниже.

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 |

Получите этот вывод - Первая строка - это заголовок, настройте по необходимости.

SampleSteps.carGetsCount (DataTable) [] [[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;
    }
...