0

I need this so that i can pass the required arguments to the class before executing that method for reporting, logging,etc., so that test cases can be executed in parallel. I am in the process of converting my keyword driven selenium framework to BDD Gherkin selenium framework .In Keyword driven framework, i get the keywords from Excel , pass the required parameters to the class through Java reflection before executing the method

    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);
novice
  • 43
  • 11
  • Maybe this helps - https://stackoverflow.com/questions/50401007/extracting-cucumber-step-name-at-runtime/50417763#50417763 – Grasshopper May 24 '18 at 05:37
  • Thanks @Grasshopper for looking into this and sharing the details. I did go though it and have one more question . I am not using the Junit runner and using the normal java code in the main method to invoke. How can i add "cusform.CustomFormatter" in my code ? Also I dont see an option like match.getmethodname to get the method name so that i can pass that through the Java reflection to pass the necessary arguments – novice May 24 '18 at 14:32
  • You can use the -p option to pass the custom formatter in the argv array. Refer to this http://toolsqa.com/selenium-cucumber-framework/run-cucumber-test-from-command-line-terminal/. – Grasshopper May 24 '18 at 15:04
  • To get method name in Cucumber 1.2.5 use the match.getLocation() to get the class.method(args) as a string. In Cucumber 2 use getCodeLocation() to get the same. – Grasshopper May 24 '18 at 15:05
  • I got something like this SampleSteps.userGetsCountFromAndStores(String) – Grasshopper May 24 '18 at 15:10
  • Thanks @Grasshopper for the details. I can see match.getLocation() but when i use the following code after adding "-p" option, its not working String [] argv = new String[]{ "-g","businesscomponents_walmart" ,"./Features" ,"-t","@P1,@P2" //,"-n","Validate_login_search_using_sku_id" ,"-p","./src/support_libraries/CustomFormatter" }; ClassLoader contextClassLoader = Thread.currentThread().getContextClassLoader(); byte exitstatus = Main.run(argv, contextClassLoader); – novice May 24 '18 at 16:10
  • I am getting the following error :Exception in thread "main" cucumber.runtime.CucumberException: Couldn't load plugin class: ./src/support_libraries/CustomFormatter – novice May 24 '18 at 16:11
  • Use the package structure of the class. – Grasshopper May 24 '18 at 16:20
  • Thank you so much. I am now able to get the method name but the problem now is how do i return the method name back to main method and pass it to Java Reflection – novice May 24 '18 at 17:42
  • Not sure I understand... Can you add the relevant code to the question? I am not sure why Java Reflection is needed. – Grasshopper May 24 '18 at 17:56
  • Currently in my Keyword driven framework, I am getting the keywords(method names ) from the excel sheet and pass them to Reflection class to choose the class , the method belongs to and pass the required variables to maintain the thread ( parallel execution) . Now after i convert to BDD, i want to return the method name from Step definition and pass it to Reflection so that i dont have to rewrite the entire framework again.Can you share your email id and i can share the code – novice May 24 '18 at 18:11
  • What version of cucumber? Cucumber 2 is the way to go. Basically you just need the methods to be called for a scenario. I am guessing you will need a list of methods for a single scenario? But how will you stop cucumber from executing the matching stepdefinition code? – Grasshopper May 24 '18 at 18:49
  • This is the dependency I am using info.cukes cucumber-java 1.2.5 Yes i need the list of methods for every test case . Can we just read the first Gherkin statement, go to the step definition , return the method to be executed, pass it to Reflection,execute that method , come back and read the next Gherkin statement of the same test cases and so on ? – novice May 24 '18 at 18:53
  • To stop cucumber from executing the stepdefinitions you will need to pass "-d" or "--dry-run" option to the argv array. Better option would be get a list of all stepdefinition methods for all the features given to the Main class. But this will require you to override the default behaviour of cucumber framework code. For starters you will need to figure out a container to get all the StepDefinition and HookDefinition properly. – Grasshopper May 24 '18 at 20:04
  • Classes like Runtime, CucumberScenario and others would require changes. Basically everywhere there is a matching method or a hook or background method you will need to add to the container. And keep on returning it up the chain. – Grasshopper May 24 '18 at 20:04
  • Will have a look later on if there is an easy way out. Also any reason you r using an old cucumber version. Cucumber 2 is totally changed. Though you are hardly using any framework feature. Having said all that not much in favor of this approach, sounds like a huge hack. Cucumber supports parallel execution pretty seamlessly. – Grasshopper May 24 '18 at 20:10
  • Thank you @Grasshopper . The reason behind this approach are two things : One is to utilize the existing keyword driven framework components and the other is to incorporate BDD approach quickly ( in fact in a week's time ). I could only think of this approach . Let me know if there is a better way to do it – novice May 24 '18 at 20:44
  • Figured it out. Added the answer below. Maybe this helps. – Grasshopper May 25 '18 at 20:33

1 Answers1

1

This was much easier to do than I thought. This just required modifying couple of lines of one class (Runtime.java) to figure out all the hook and step methods. All it then needed was to run in dryrun mode set to true to get all the details.

Override Runtime.java behaviour -

  1. Download the 1.2.5 class from this link https://github.com/cucumber/cucumber-jvm/blob/v1.2.5/core/src/main/java/cucumber/runtime/Runtime.java

  2. Create a package cucumber.runtime in the classpath and copy the Runtime class inside it.

3.In private method runHooks(line 209) comment out lines 210 and 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. In private method runHookIfTagsMatch(line 217) add the line 210 before existing line 224. Basically if in dryrun mode do not execute the hook. The try block contains this code. if(!runtimeOptions.isDryRun()) hook.execute(scenarioResult);

CustomFormatter - This will now store all the details in a ThreadLocal variable.

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

If you uncomment the print lines in the close() method you can see the output as something like this.

Step Methods Match - Corresponds to 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]}}

Before Hook Matches -Corresponds to 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]}

After 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]}

This is for a run of a single feature file as below. If you have multiple feature files you will have multiple feature keys in featureDetails map. The hooks will be added to the hook maps.

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"

Important - The key which binds the three together is the Scenario object. Pretty easy to iterate the featureDetails map and get the before hook if available, then available steps and then after hook. For getting hook method names use

ThreadLocal Class -

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 class -

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

Check details in store -

You can use the below code as a sample to see the details inside the maps and in 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()));
                        }));

For the above feature file got this output

Scenario Line Number 8 Before Hook SampleSteps.before() Steps SampleSteps.userGetsCountFromAndStores(String) [Car0] Steps SampleSteps.userGetsCountFromAndStores(String) [Car1] After Hook SampleSteps.afterOne(Scenario) Scenario Line Number 15 Before Hook SampleSteps.before() Steps SampleSteps.userGetsCountFromAndStores(String) [Car0] Steps SampleSteps.userGetsCountFromAndStores(String) [Car1] After Hook SampleSteps.afterOne(Scenario)

This will also work for scenariooutlines.


UPDATED -

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

Results

{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=[]} Scenario Line Number 4 Steps SampleSteps.openbrowser() []


UPDATED

Need to add some code to the StepDefinitionMatch class. Similar to what u had done for Runtime.java download the 1.2.5 class at - https://github.com/cucumber/cucumber-jvm/blob/v1.2.5/core/src/main/java/cucumber/runtime/StepDefinitionMatch.java. Copy this class to the existing cucumber.runtime package. Then add the following method --

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

That is it. Call this method in the existing print method like below.

ee.getValue().stream().forEach(s -> System.out.println("Steps " + s.getLocation() + " " + s.getArguments() + " " + s.getDataTableData()));

For this feature file

 Scenario: Scenario Four
    And car gets count
      | car  | owner      |
      | Car1 | OwnerOne   |
      | Car2 | OwnerTwo   |
      | Car3 | OwnerThree |

Got this output - The first line is the header, customize as required.

SampleSteps.carGetsCount(DataTable) [] [[car, owner], [Car1, OwnerOne], [Car2, OwnerTwo], [Car3, OwnerThree]]


UPDATE

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;
    }
Grasshopper
  • 8,908
  • 2
  • 17
  • 32
  • Thanks a lot for your efforts and helping me out . I tried all the steps you told me but i am getting the following :{mytest_1.feature={gherkin.formatter.model.Scenario@a072f6=[cucumber.runtime.StepDefinitionMatch@c07d28]}} {gherkin.formatter.model.Scenario@a072f6=[]} {gherkin.formatter.model.Scenario@a072f6=[]} When i use "Check details in store" code in "CustomFormatter" , I am getting an error - CustomFormatter.close(CustomFormatter.java:145) Error line - sd.getFeatureDetails().entrySet().stream().forEach( . In a nutshell, I am not able to see the method name – novice May 26 '18 at 21:55
  • Feature File : Feature: UI Automation @P1 Scenario: Validate_Home_page Given the customer opens launches the homepage Step Definition - @Given("^the customer opens launches the homepage$") public void openbrowser() { } Java Code - String[] argv = new String[] { "-g", "stepDefinition", "./Features", "-t", "@P1" , "-p", "support_libraries.CustomFormatter","-d"}; ClassLoader contextClassLoader = Thread.currentThread().getContextClassLoader(); byte exitstatus = Main.run(argv, contextClassLoader); – novice May 26 '18 at 22:18
  • I have used exactly the feature files, step definition and java code and everything is working. The feature file you are using is not correct as there are 2 scenario entries without steps. I have copied the code and results. – Grasshopper May 27 '18 at 07:32
  • Thank you . It worked . My Bad . It was my mistake . I have another problem now . I am trying to put all the method names in a Map and return it to run() in Runtime class from CustomFormatter class but it is not allowing me to : Map map = formatter.close(); It is displaying an error message - Type mismatch: cannot convert from void to Map .I think we are overriding the formatter at the run time and hence its not allowing . Any idea how to overcome this issue ? – novice May 28 '18 at 15:56
  • I need to get back the method names by using Map map = Main.run(argv, contextClassLoader); – novice May 28 '18 at 15:57
  • Access the methods from the ThreadLocal class. StepHookDetails sd = ThreadLocalStepHookDetails.get(). StepHookDetails has the getter methods to get the stepdefinitions, before and after hooks. – Grasshopper May 28 '18 at 16:08
  • If i access the methods from ThreadLocal class. StepHookDetails sd = ThreadLocalStepHookDetails.get() , then i will not be able to pass the arguments required for parallel execution. Currently i use reflection.execute_Actions(method_name, driver, rm_var, log4j, excel_path, screenshots_path, report, childTest, consolidated_childTest, mode); If i can get the method names , I will pass them here and i would require no changes in my existing framework – novice May 28 '18 at 16:19
  • The method name is inside the StepDefinitionMatch object of the Map>>. Iterate the map, similar to the print code. Use stepdefinitionmatch.getLocation to get method names. That is the whole purpose of the StepDefinitionMatch to get hold of the stepdefinition method. Not sure if running each stepdefinition is a good idea. I think scenarios should be run in parallel rather than methods inside it. – Grasshopper May 28 '18 at 16:27
  • I can get the list of method names now but how do i return those . I dont want to invoke the methods from step definition files because i cannot pass the required arguments from there . I want to return all the method names and use my existing framework to invoke them one after the other for a test case and i have to run the test cases in parallel and not the methods in a test case – novice May 28 '18 at 16:51
  • You need to call StepHookDetails sd = ThreadLocalStepHookDetails.get(); method after the call to -- byte exitstatus = Main.run(argv, contextClassLoader); in the same method of the class. See the edited main method. ThreadLocal will let u access the same stored details as long as it is in the current thread. You do not need to return anything from anywhere. – Grasshopper May 28 '18 at 17:09
  • Awesome . Now i understood . Sorry for being such a naive . Once again I really appreciate your time and effort in helping me out . I will get back in case i face any other issues . – novice May 28 '18 at 17:40
  • Is there a way i can read the data table from the feature file for every scenario and store them in a list before i pass the method name and the required test data to my Java Reflection Scenario: TC_05_UI_Validate_error_message_incorrect_Login Given I am a user in the website's home page And I log in into the application with incorrect credentials | Username | Password | | novice | Test@153 | . Currently i am getting all the methods associated with the scenario – novice Jun 06 '18 at 13:52
  • The datatable data should be stored inside the getArguments() for each stepdefinition.. – Grasshopper Jun 06 '18 at 15:35
  • My step definition is public WebDriver incorrect_signin(DataTable table) throws Throwable { return driver; } I get the output as : StepDefinitions.incorrect_signin(DataTable) [] Argument is null – novice Jun 06 '18 at 20:19
  • I think details will be inside the Step variable. The step() method in the custom formatter has a step argument. Check it out – Grasshopper Jun 06 '18 at 20:45
  • I am sorry .I dont understand what you said . I just see this in Custom Formatter public void step(Step step) { } and i see the argument but not sure how to use it – novice Jun 06 '18 at 22:01
  • Thanks a lot once again . You are my savior :) :) – novice Jun 10 '18 at 01:29
  • One more question. Is there a way to read the data table in such a way that we store "car" as the key and "Car1;Car2;Car3" as values in a hash map so that test data retrieval becomes easy during test execution instead of using a List> . I tried doing it but could not get the desired results – novice Jun 10 '18 at 16:09
  • Thanks a lot .Works like a charm . I am getting an exception - java.lang.IndexOutOfBoundsException: Index: 4, Size: 4 for the following data table. Other than that it works fine . I am not sure if i can use the data table like that . – novice Jun 12 '18 at 01:49
  • | Username | Password | Iteration | Header_1 | Header_2 | | Tester | Test1234 | 4 | H11 | H21 | | H12 | H22 | | H13 | H23 | | H14 | H24 | – novice Jun 12 '18 at 01:53
  • Does not look like a valid table... you will atleast need to add spaces for data that is missing. – Grasshopper Jun 12 '18 at 06:08
  • Got it and thanks . I added the empty spaces as you suggested and used trim function while using the test data . It worked perfectly fine . I was not sure about the data table format earlier – novice Jun 12 '18 at 16:00
  • Is there a way i can get list of scenario names alone tagged as "@Regression" in the feature files String[] argv = new String[] { "-g", HelperClass.loadFromPropertiesFile().getProperty("components"), HelperClass.loadFromPropertiesFile().getProperty("featurefilepath") , "-t", "@Regression" , "-p","support_libraries.CustomFormatter" , "-d" }; ClassLoader contextClassLoader = Thread.currentThread().getContextClassLoader(); Main.run(argv, contextClassLoader) – novice Jun 14 '18 at 16:26
  • I got it using System.out.println(ee.getKey().getName()); – novice Jun 14 '18 at 16:29
  • U must have an amazing existing testing framework to be hacking cucumber to suit its needs... – Grasshopper Jun 14 '18 at 20:03
  • Ha ha :) :) I just dont have enough time to implement a new BDD framework . I am facing one more issue now . I am getting the following error : Exception in thread "main" java.lang.ClassCastException: gherkin.formatter.model.Match cannot be cast to cucumber.runtime.StepDefinitionMatch . Unable to resolve this . The issue is with the line : stepDetails.add((StepDefinitionMatch) match) in CustomFormatter – novice Jun 15 '18 at 20:45
  • What is the gherkin jar version? – Grasshopper Jun 15 '18 at 21:00
  • i did not update Cucumber . My Gherkin dependency is info.cukes gherkin 2.12.2 provided – novice Jun 15 '18 at 21:04
  • String[] argv = new String[] { "-g","components","src/features", "-t", "@P1" , "-p","support_libraries.CustomFormatter" , "-d" }; ClassLoader contextClassLoader = Thread.currentThread().getContextClassLoader(); Main.run(argv, contextClassLoader); StepHookDetails sd = ThreadLocalStepHookDetails.get(); sd.getFeatureDetails().entrySet().stream().forEach(e -> e.getValue().entrySet().stream().forEach(ee -> { System.out.println(ee.getKey().getName()); })); I am getting error in this code. It was working fine till yesterday – novice Jun 15 '18 at 21:09
  • Comment this line and check again. – Grasshopper Jun 15 '18 at 21:24
  • I did try after commenting the line :stepDetails.add((StepDefinitionMatch) match) in CustomFormatter and it works. It fetches the scenario names tagged to "@Regression" but it does not read the stepDetails which are required for getting the step definitions mapped to the Gherkin statements – novice Jun 15 '18 at 21:28
  • i copied ur code and tried on my setup and it returned the scenario name -- Scenario Line Number 9 Scenario Four Steps SampleSteps.carGetsCount(DataTable) [] {owner=[OwnerOne, OwnerTwo, OwnerThree], car=[Car1, Car2, Car3]} For the feature file in answer – Grasshopper Jun 15 '18 at 21:36
  • Saw this error : Thread [main] (Suspended (exception ClasscastException)) $Proxy9.match(Match) line;not available . I think I found the issue. This is happening because its not able to handle multi threading . If i give the number of threads as "1 or 2", i dont see this error but I would be running with "20-25 threads " – novice Jun 16 '18 at 02:44
  • Run the code where u are hacking cucumber in a sungle thread. Aftrr tht u can do multi threaded – Grasshopper Jun 16 '18 at 18:05
  • Thanks . I was able to debug, identify the exact issue and resolve this .My Gherkin statement had few things in upper case and the step definitions were in lower case . Thats what has caused the issue . Once i modified , everything worked fine. It was a very small issue and took me a very long time to identify as i dont have Natural plugin installed in my client machine because of security issues – novice Jun 18 '18 at 15:07
  • Hope you are doing good. Our client now wants to implement a Cucumber framework with Multi Threading capability & Extent Reports . This is to make use of all the Cucumber features which are available .Can you please guide and let me know if there is any existing cucumber framework which would serve our purpose – novice Aug 12 '18 at 17:03
  • Best option would be google for parallel cucumber. I think there is some threading support for extent. check the documentation. There is planned to be native support for parallel running in cucumber 4 which is currently under development. Check it out at https://github.com/cucumber/cucumber-jvm, and the tag 4.0.0. Also with this the reporting supports threading. – Grasshopper Aug 14 '18 at 20:14
  • Thanks Grasshopper.I will look into it. I have one more question . With my existing framework, i am able to get the test cases to be executed from the feature files and pass the test cases in the threads after invoking the threads to get the methods , test data and execute them with your help. Is there a way i can get only the test cases and then pass them through multiple threads to execute using Cucumber runner (not the modified one )and get the test execution results .This way I dont have to worry about the parallel threading and use my own code – novice Aug 20 '18 at 23:04
  • First impression as i do not know ur framework, wont be able to use cucumber runner by passing test case. It has its own logic of picking them from the feature file. U can try hacking into existing logic but it will be tough sailing. Try cucumber out off the box with parallel. U can use junt maven surefire or failsafe plugin for parallel. Search in SO u will get many options. – Grasshopper Aug 21 '18 at 20:20
  • Thanks Grasshopper. I will look into it – novice Aug 22 '18 at 14:23
  • I was able to build a wrapper for multi threading that would run the scenarios in the feature files in parallel. In this case, I am generating consolidated Extent report but I would require individual Extent report for every test case so that i can upload them to ALM against each test case. I am trying the following and it does not work – novice Aug 23 '18 at 20:30
  • String[] argv = new String[] { "-g", FileReaderManager.getInstance().getConfigReader().getGluepath() , FileReaderManager.getInstance().getConfigReader().getFeaturefilepath() , "-n", testcasename , "-p", Utils.consolidated_extent_reports_path , "-p", tc_html_reports_path , "-p", tc_json_reports_path ,"-m" }; ClassLoader contextClassLoader = Thread.currentThread().getContextClassLoader(); Main.run(argv, contextClassLoader); – novice Aug 23 '18 at 20:32
  • How are u defining every 'test case'? Every feature file or every scenario? Dont know much about Extent, but it would seem for every 'test case' u can open up a new file for writing the result. Maybe u are just giving the same report file to extent. – Grasshopper Aug 25 '18 at 09:05