Hot questions for Using Cucumber in feature file

Top Java Programmings / Cucumber / feature file

Question:

I have multiple scenarios listed in a feature file and I need to run only a single failing scenario (for debugging purposes).

I have mentioned @tag before the scenario but while in Test Runner file when given this tag it is running entire feature file. Please help me out how to put it correctly.

TEST Runner file -

tags={"@Islamic_User_check"},

Answer:

If you want to run a specific scenario using cucumber you need to provide the line number the scenario starts on like:

cucumber features/test.feature:7

if you use the @ feature it should point to a txt file where the line number is still given.

Source: https://www.relishapp.com/cucumber/cucumber/docs/cli/run-specific-scenarios

Hope this helps

Question:

I have below feature files (Separate feature files) in src/test/resources/feature/ and I would like to run them in parallel. Like: One feature file has to execute in chrome and another one has to execute in firefox as mentioned @Tags name.

Feature: Refund item

@chrome
  Scenario: Jeff returns a faulty microwave
    Given Jeff has bought a microwave for $100
    And he has a receipt
    When he returns the microwave
    Then Jeff should be refunded $100

Feature: Refund Money

@firefox
  Scenario: Jeff returns the money
    Given Jeff has bought a microwave for $100
    And he has a receipt
    When he returns the microwave
    Then Jeff should be refunded $100

Can somebody assist me to achieve this.I'm using cucumber-java 1.2.2 version, and AbstractTestNGCucumberTests using as runner. Also, let me know how can I create a Test Runner dynamically by using feature files and make them run in parallel.


Answer:

Update: 4.0.0 version is available at maven central repository with bunch of changes.for more details go here.

Update: 2.2.0 version is available at maven central repository.

You can use opensource plugin cucumber-jvm-parallel-plugin which has many advantages over existing solutions. Available at maven repository

   <dependency>
     <groupId>com.github.temyers</groupId>
     <artifactId>cucumber-jvm-parallel-plugin</artifactId>
     <version>2.1.0</version>
   </dependency>
  1. First you need to add this plugin with required configuration in your project pom file.

    <plugin>
      <groupId>com.github.temyers</groupId>
      <artifactId>cucumber-jvm-parallel-plugin</artifactId>
      <version>2.1.0</version>
      <executions>
         <execution>
         <id>generateRunners</id>
         <phase>generate-test-sources</phase>
         <goals>
           <goal>generateRunners</goal>
         </goals>
         <configuration>
             <!-- Mandatory -->
             <!-- comma separated list of package names to scan for glue code -->
             <glue>foo, bar</glue>
             <outputDirectory>${project.build.directory}/generated-test-sources/cucumber</outputDirectory>
              <!-- The directory, which must be in the root of the runtime classpath, containing your feature files.  -->
               <featuresDirectory>src/test/resources/features/</featuresDirectory>
              <!-- Directory where the cucumber report files shall be written  -->
              <cucumberOutputDir>target/cucumber-parallel</cucumberOutputDir>
              <!-- comma separated list of output formats json,html,rerun.txt -->
              <format>json</format>
              <!-- CucumberOptions.strict property -->
              <strict>true</strict>
              <!-- CucumberOptions.monochrome property -->
              <monochrome>true</monochrome>
              <!-- The tags to run, maps to CucumberOptions.tags property you can pass ANDed tags like "@tag1","@tag2" and ORed tags like "@tag1,@tag2,@tag3" -->
             <tags></tags>
             <!-- If set to true, only feature files containing the required tags shall be generated. -->
             <filterFeaturesByTags>false</filterFeaturesByTags>
             <!-- Generate TestNG runners instead of default JUnit ones. --> 
             <useTestNG>false</useTestNG>
             <!-- The naming scheme to use for the generated test classes.  One of 'simple' or 'feature-title' --> 
            <namingScheme>simple</namingScheme>
            <!-- The class naming pattern to use.  Only required/used if naming scheme is 'pattern'.-->
            <namingPattern>Parallel{c}IT</namingPattern>
            <!-- One of [SCENARIO, FEATURE]. SCENARIO generates one runner per scenario.  FEATURE generates a runner per feature. -->
            <parallelScheme>SCENARIO</parallelScheme>
            <!-- This is optional, required only if you want to specify a custom template for the generated sources (this is a relative path) -->
            <customVmTemplate>src/test/resources/cucumber-custom-runner.vm</customVmTemplate>
            </configuration>
           </execution>
         </executions>
       </plugin>
    
  2. Now add below plugin just below above plugin which will invoke runner classes generated by above plugin

        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-surefire-plugin</artifactId>
            <version>2.19</version>
            <configuration> 
                <forkCount>5</forkCount>
                <reuseForks>true</reuseForks>
                <includes>
                    <include>**/*IT.class</include>
                </includes>
            </configuration>
        </plugin>
    
  3. Above two plugins will do magic for cucumber test running in parallel (provided you machine also have advanced hardware support).

  4. Strictly provided <forkCount>n</forkCount> here 'n' is directly proportional to 1) Advanced Hardware support and 2) you available nodes i.e. registered browser instances to HUB.

  5. One major and most important changes is your WebDriver class must be SHARED and you should not implement driver.quit() method, as closing is take care by shutdown hook.

    import cucumber.api.Scenario;
    import cucumber.api.java.After;
    import cucumber.api.java.Before;
    import org.openqa.selenium.OutputType;
    import org.openqa.selenium.WebDriver;
    import org.openqa.selenium.WebDriverException;
    import org.openqa.selenium.firefox.FirefoxDriver;
    import org.openqa.selenium.support.events.EventFiringWebDriver;
    
    public class SharedDriver extends EventFiringWebDriver {
        private static WebDriver REAL_DRIVER = null;
    
    
    
        private static final Thread CLOSE_THREAD = new Thread() {
            @Override
            public void run() {
                REAL_DRIVER.close();
            }
        };
    
        static {
            Runtime.getRuntime().addShutdownHook(CLOSE_THREAD);
        }
    
        public SharedDriver() {
            super(CreateDriver());
        }
    
        public static WebDriver CreateDriver() {
            WebDriver webDriver;
            if (REAL_DRIVER == null)
                webDriver = new FirefoxDriver();
            setWebDriver(webDriver);
            return webDriver;
        }
    
        public static void setWebDriver(WebDriver webDriver) {
            this.REAL_DRIVER = webDriver;
        }
    
        public static WebDriver getWebDriver() {
            return this.REAL_DRIVER;
        }
    
        @Override
        public void close() {
            if (Thread.currentThread() != CLOSE_THREAD) {
                throw new UnsupportedOperationException("You shouldn't close this WebDriver. It's shared and will close when the JVM exits.");
            }
            super.close();
        }
    
        @Before
        public void deleteAllCookies() {
            manage().deleteAllCookies();
        }
    
        @After
        public void embedScreenshot(Scenario scenario) {
            try {
                byte[] screenshot = getScreenshotAs(OutputType.BYTES);
                scenario.embed(screenshot, "image/png");
            } catch (WebDriverException somePlatformsDontSupportScreenshots) {
                System.err.println(somePlatformsDontSupportScreenshots.getMessage());
            }
        }
    }
    
  6. Considering you want to execute more than 50 threads i.e. same no of browser instances are registered to HUB but Hub will die if it doesn't get enough memory therefore to avoid this critical situation you should start hub with -DPOOL_MAX=512 (or larger) as stated in grid2 documentation.

    Really large (>50 node) Hub installations may need to increase the jetty threads by setting -DPOOL_MAX=512 (or larger) on the java command line.

    java -jar selenium-server-standalone-<version>.jar -role hub -DPOOL_MAX=512

Question:

When I submit a single feature file it works perfectly. I want to pass features folder path which has multiple feature files into runner script. Can anyone help to execute multiple feature files?

All feature files have same steps but data is different and file name is different.

@RunWith(Cucumber.class)

@CucumberOptions(format = {"pretty"}, features =
"C:\\TESTER\\Execution\\uidata\\featurefiles\\",
        glue={"com.test.auto.stepdefs"},dryRun=false) 

public class CucumberTest { 

}

I appreciate you help.


Answer:

The features path must be relative to your project classpath. For example it can look like this:

@CucumberOptions(features = {"classpath:features_folder1", "classpath:features_folder2"}, ...)

or

@CucumberOptions(features="src/test/resources")

Question:

Currently, I have found that cucumber test suite runs the feature files alphabetically.

Please let me know if there is any option/configuration that I might be missing. Thanks.


Answer:

Cucumber features/scenarios are run in Alphabetical order by feature file name.

However, if you specifically specify features, they should be run in the order as declared. For example:

@Cucumber.Options(features={"automatedTestingServices.feature", "smoketest.feature"})

Question:

I'm using QAF and it's amazing tool, but i have one problem. Are there any ways to parameterize cucumber feature steps with custom data provider as it's done in BDD files?

For example, we can insert data from external file

Examples: {'datafile':'resources/testdata.txt'}

In .BDD it's done like this:

SCENARIO: Data provider with testng method argument and context
META-DATA: {"dataProvider":"dp-with-testngmethod-contex", "dataProviderClass":"com.qmetry.qaf.automation.impl.CustomDataProvider"}
# Comment '${value}'
END

Answer:

If you found in-built data-providers does not satisfy your need then you can provide custom data provider. In case of gherkin you can provide it with Examples:

Examples: {"dataProvider":"dp-with-testngmethod-contex", "dataProviderClass":"com.qmetry.qaf.automation.impl.CustomDataProvider"}

Any of the meta-data for data-provider can be used with Examples. Moreover with latest BDD2 syntax you can also provide it as below:

@dataProvider:dp-with-testngmethod-contex
@dataProviderClass:com.qmetry.qaf.automation.impl.CustomDataProvider
@regression 
Scenario: my scenario
...

Question:

I just created simple java file which is used to execute the feature file through cucumber, but Its failed, and throws following run time exception

Exception in thread "main" cucumber.runtime.CucumberException: Error parsing feature file C:/Users/XXX/XXXX/src/test/java/RunTest.java
    at cucumber.runtime.FeatureBuilder.parse(FeatureBuilder.java:133)
    at cucumber.runtime.model.CucumberFeature.loadFromFeaturePath(CucumberFeature.java:102)
    at cucumber.runtime.model.CucumberFeature.load(CucumberFeature.java:54)
    at cucumber.runtime.model.CucumberFeature.load(CucumberFeature.java:34)
    at cucumber.runtime.RuntimeOptions.cucumberFeatures(RuntimeOptions.java:201)
    at cucumber.runtime.Runtime.run(Runtime.java:109)
    at cucumber.api.cli.Main.run(Main.java:36)
    at cucumber.api.cli.Main.main(Main.java:18)
Caused by: gherkin.lexer.LexingError: Lexing error on line 1: 'package test.java;

import cucumber.api.CucumberOptions;
import cucumber.api.testng.AbstractTestNGCucumberTests;

    @CucumberOptions(features="src/test/resources/")
    public class RunTest extends AbstractTestNGCucumberTests {
    }

Feature file:

Feature: Search India on BBC website and verify search.

@Search
  Scenario Outline: Search India on BBC website and verify it.
    Given I open the firefox browser
    And I navigating to BBc website
    Then I click at search textbox
    And I enter "India" in search textbox
    And I click at Search button
    Then I should be taken to search page
    And I verify India on search page

Can somebody tell me how to resolve this issue?


Answer:

When using a Scenario Outline, you need to provide an "Examples" section. In this case, it looks like you don't need a scenario outline at all, so:

Feature: Search India on BBC website and verify search.

  @Search
  Scenario: Search India on BBC website and verify it.
    Given I open the firefox browser
    And I navigating to BBc website
    Then I click at search textbox
    And I enter "India" in search textbox
    And I click at Search button
    Then I should be taken to search page
    And I verify India on search page

If you do need a scenario outline, you want something like:

Feature: Search India on BBC website and verify search.

  @Search
  Scenario Outline: Search India on BBC website and verify it.
    Given I open the firefox browser
    And I navigating to BBc website
    Then I click at search textbox
    And I enter "<country>" in search textbox
    And I click at Search button
    Then I should be taken to search page
    And I verify <country> on search page

  Examples:
    | country |
    | India   |
    | China   |

Question:

I am having a java project which is built using maven.

I have multiple packages,feature files based on different functionalities. The project test structure is as below.

src
  ->test
    ->java
      ->com
        ->usercreation
          TestStepDef.java
        ->uservalidation
          TestStepDef.java
   ->resources
        ->usercreation
           usercreation.feature
        ->uservaliation
           uservalidatin.feature

I have only one RunCukesTest.java file

@RunWith(Cucumber.class)
@CucumberOptions(format = { "html:target/cucumber-html-report",
                        "json:target/cucumber-json-report.json" }, 
                        features = "src/test/resources/",
                        glue = "??????",
                        tags = {"~@ignore"}
            )
 public class RunCukesTest {

 }

In this case it runs all my feature files. But it is not able to find my specific Step definitions for the feature. So I have to give the glue option as "com.usercreation". But if I do so when it runs the uservalidation feature file it will not be able to pick up the appropriate step definition. In my use case I don't want both the step def file to be in the same package, as they have many steps with different functionalities.

Is there a possible way where I can give the glue option dynamically based on the package name the feature file is running. Or am I missing any other approach to this project.


Answer:

glue = { "classpath:com/usercreation", "classpath:com/uservalidation" },

Question:

I am trying a negative scenario for susbcription name(string) for different data type which is boolean. Examples:

|Subscription Name|Ext Id|Owner Firstname|Owner Lastname|

|true             |"423" |"abc"          |"xyz"         |

Answer:

First, I never put quotes around items in the examples table. I put quotes around the item in the step definition.

When I search for "<Ext Id>"

As for the Subscription name element, you can convert that within your step definition using How to convert String object to Boolean Object?

Question:

I'm creating an executable jar file for some of my less tech literate coworkers to run tests without having to use the command line. It's a simple gui where they select the features they want to test and the step library is packaged within.

It works fine except for one small problem. At the moment I have to specify where I call the feature files from. Right now I have this set to look for a features= {"c://Features"} folder and run whatever is in there. I would like this to be more dynamic so that they don't have to create feature folders and, using a variable I can generate through the gui they can point to whatever file they want.

My current workaround is that I simply read from what ever file they choose and create a copy within the features folder which is cleaned after every test. This is not optimal and I would like to allow my users to point to whatever folder they wish and run feature files from that folder as some of our clients don't allow us to modify their c drive. I can still write into the folder they select and create temporary file copies, that's fine. But the annotation won't let me pass in a variable, I get this error instead.

The value for annotation attribute CucumberOptions.features must be a constant expression

Answer:

You can use QMetry Automation Framework to run your gherkin. With QAF gherkin client you will be able to configure your features to run from xml configuration file. there you can specify one of more dir or feature file to run as well as you can apply filter, or you can configure your tests to run on different platforms. Here is the sample xml configuration file

<test name="Gherkin-QAF-Test">
   <parameter name="scenario.file.loc" value="resources/features" />
   <classes>
      <class name="com.qmetry.qaf.automation.step.client.gherkin.GherkinScenarioFactory" />
   </classes>
</test>

More over you can set scenario.file.loc as command line argument or in properties file.

Question:

I try to add a tag in my feature file (using cucumber plugin within eclipse) but when I run my feature file it gives me an error:

Exception in thread "main" gherkin.TagExpression$BadTagException: Bad tag: "env" What am I doing wrong?

What I want is when I run the test, I want it to set the environment first before running the scenario:

Feature example:

Feature: Log into an account

@env
Scenario: Log Into Account With Correct Details
    Given User navigates to stackoverflow website

Class for Environment setup:

    @Before("env")
        public void setEnvironment() {
System.setProperty("webdriver.chrome.driver", "xxx//chromedriver.exe");
        this.driver = new ChromeDriver();
            ActiveEnvironment = LivePortal;
            EnvironmentUsed.add(ActiveEnvironment); 
            driver.manage().window().maximize();
        }

Answer:

Need to add '@' for the Before annotation

@Before("@env")
public void setEnvironment() {

Question:

Im trying to figure out how to parse date fields from my cucumber feature files in my step definitions.

class Person{ 
  String name
  LocalDate dob
}

scenario: do something with people
Given  list of people:
                     |name|dob|
                     | john| 20-09-2001|

@Given("^list of people:")
public void doSomething(List<Person> people) {

}

Please note i have no access to the Person class, Im sure i have to either write my own converter or register a converter written by someone from some library, after searching around the only options i can see are to change them pojo with a @Transform on the java.time.LocalDate field.

I'm currently getting the following exception

cucumber.runtime.CucumberException:              cucumber.deps.com.thoughtworks.xstream.converters.ConversionException: Cannot deserialize object with new readObject()/writeObject() methods
---- Debugging information ----
class               : java.time.LocalDate
required-type       : java.time.LocalDate
converter-type      : cucumber.deps.com.thoughtworks.xstream.converters.reflection.SerializableConverter
path                : /list/com.pkg.Person/dob

I have tried changing the dateformat to yyyy-MM-dd, that usually works but not on this occasion. I would be gratefull for any pointers on how to setup and register a custom converter

my cucumber dependencies are as follows, i can chane these if required to newer versions if it makes any difference.

    <dependency>
        <groupId>io.cucumber</groupId>
        <artifactId>cucumber-java</artifactId>
        <version>2.4.0</version>
    </dependency>

    <dependency>
        <groupId>io.cucumber</groupId>
        <artifactId>cucumber-junit</artifactId>
        <version>2.4.0</version>
        <scope>test</scope>
    </dependency>

    <dependency>
        <groupId>io.cucumber</groupId>
        <artifactId>cucumber-spring</artifactId>
        <version>2.4.0</version>
    </dependency>

Answer:

Cucumber does not support automatic conversion of the new java date time classes. But it does support conversion to the old util Date class which is of no use as you do not have write access to the dataobject.

For this to work you will need to use the @XStreamConverters annotation on the test runner. This will add the custom xstream converter to the out of the box converters in cucumber.

@RunWith(Cucumber.class)
@CucumberOptions(plugin = { ""}, tags = { "" }, glue = "stepdefs",
        features = "" ) --> use your own values
@XStreamConverters(@XStreamConverter(LocalDateCon.class))
public class RunSampleTest {

Now the converter class to parse the string into LocalDate and create the collection of dataobjects. This will support dates like "15-05-2016". Just change the DEFAULT_DATE_PATTERN according to your date format.

public class LocalDateCon implements Converter{

    public boolean canConvert(Class type) {
        //return type.equals(LocalDate.class);
        return LocalDate.class.isAssignableFrom(type);
    }

    private static final String            DEFAULT_DATE_PATTERN = "dd-MM-yyyy";
    private static final DateTimeFormatter DEFAULT_DATE_FORMATTER = DateTimeFormatter.ofPattern(DEFAULT_DATE_PATTERN);

    public void marshal(Object value, HierarchicalStreamWriter writer, MarshallingContext context) {
        LocalDate  date = (LocalDate) value;
        String result = date.format(DEFAULT_DATE_FORMATTER);
        writer.setValue(result);
    }

    public Object unmarshal(HierarchicalStreamReader reader, UnmarshallingContext context) {
        LocalDate result = LocalDate.parse(reader.getValue(), DEFAULT_DATE_FORMATTER);
        return result;
    }

}

Also you will not be able to use @Transform annotation cleanly as it works only for a single value and not a collection. I used cleanly as one will need to do the object creation in the converter code which is messy.

Question:

 @Before
  public void quit_if_tagged_scenario_failed(Scenario scenario) {
    if (!isTagged(scenario) && prevScenarioFailed)
      throw new IllegalStateException("An important scenario has failed!     Cucumber wants to quit.");
  }

I'm using this method to check if the previuos scenario failed. If failed I want to skip all the scenarios in that feature file.So the problem here is if I’m running two feature files the last scenario in the feature file failed and the first step of next feature will also fails because cucumbers previous scenario from past feature file is failed. Do you know how to handle that kind of situation? Your help will be greatly appreciated.


Answer:

Cucumber scenarios should not be dependent on each other.

According to the Cucumber best practices, there shouldn’t be any sort of coupling between scenarios. Or in other words, there should be no state that persists between scenarios.

Just as an example why this is a bad practice consider a case when one scenario step adds a record to a database, while the subsequent scenarios depend on the existence of that record. This may work, but will create a problem if the order in which scenarios run changes, or they are run in parallel.

Try to review your approach and see how can you define your scenarios differently to avoid coupling. Good luck.

Question:

I have a case for a feature file where we have to test emails and we can't. So we decided to mark the whole feature file as @manualTesting so that people know that it has to be manually tested.

I know how to create an annotation to be executed before or after but is there a way that when we mark some feature file with @manualTesting it never gets executed.

Note:- I don't want to add any @excluded or @disabled annotation.


Answer:

Tags in cucumber options will be the best way to do it.

If u r using 2.x version of cucumber tags dependency in your project then

tags={ "not @manualtesting"}

And if you are using 1x version then use

tags={"~@manualtesting"}

This will skip all features or scenarios tagges with @manualtesting.

Question:

Is there any way to declare a variable in a feature file to then use in a cucumber test? Something like this:

myFile.feature

Given whenever a value is 50

myFile.java

@Given("^whenever a value is 50$")
public void testing(value) {
    assertEqual(value, 50);
}

Honestly, I don't even know what this would look like. But I would love to not have to declare a value in both the feature file AND the Cucumber test. Thanks!


Answer:

Yes you can! Write the Given-step in the feature.

Feature: foobar

Scenario: something
    Given whenever a value is 50

Then run it as a JUnit test. You will see something like this in the console.

@Given("^whenever a value is (\\d+)$")
public void whenever_a_value_is(int arg1) throws Throwable {
    // Write code here that turns the phrase above into concrete actions
    throw new PendingException();
}

Then you can copy+paste it and change it to:

@Given("^whenever a value is (\\d+)$")
public void whenever_a_value_is(int value) {
    assertEquals(value, 50);
}

Question:

I want to pass an argument to karate graphql test from selenium java test. I tried to do that this way, but it didn't work.

HashMap<String, Object> args = new HashMap<String, Object>();
args.put("argument1", "value1");
Map<String, Object> result = CucumberRunner.runFeature(featureFile, 
args, true);

I tried to put that value in karate file in ways like

<argument1>

or

#(argument1)

but literally this text was passed to query in karate test. Have someone done that by karate?

Here you have fragment of my feature file:

Given text query =
"""
{
  element(name:"<argument1>") {
    name
  }
}
"""
And request {query: '#(query)'}
When method post
Then status 200
* print response

Answer:

I think you missed a replace, try this:

Given text query =
"""
{
  element(name:"<argument1>") {
    name
  }
}
"""
And replace query.argument1 = argument1
And request {query: '#(query)'}
When method post
Then status 200

Question:

I am trying to run cucumber feature file on Eclipse but getting following error. "Error: Could not find or load main class cucumber.api.cli.Main"

Gradle code (build.gradle)

apply plugin: 'java'

configurations {
    cucumberRuntime {
        extendsFrom testRuntime
    }
}

task cucumber() {
    dependsOn assemble, compileTestJava
    doLast {
        javaexec {
            main = "cucumber.api.cli.Main"
            classpath = configurations.cucumberRuntime + sourceSets.main.output + sourceSets.test.output
            args = ['--plugin', 'pretty', '--glue', 'gradle.cucumber', 'src/test/resources']
        }
    }
}

dependencies {
    testCompile 'io.cucumber:cucumber-java:3.0.2'
    testCompile 'io.cucumber:cucumber-junit:3.0.2'

    testCompile 'junit:junit:4.12'
}

repositories {
    mavenCentral()
}

Feature file (add.Feature)

@tag
Feature: Title of your feature
  I want to use this template for my feature file

  @tag1
  Scenario: Title of your scenario
    Given I have the calculator
    When I enter input1 and input2
    And I press add button
    Then I get output

I am right clicking on feature file. Then selecting run as and pressing on cucumber feature. Thanks in advance.


Answer:

I forgot to add runner class. Below is the code for runner class. After adding this class, I am able to run the feature file

runcukestest.java

package cucumber;

import cucumber.api.junit.Cucumber;
import org.junit.runner.RunWith;
import cucumber.api.CucumberOptions;

@RunWith(Cucumber.class)
@CucumberOptions(plugin = {"pretty"})
public class runcukestest {

}

Question:

I'd like to have a single testNG/Cucumber runner & single testng @Test that allows me to pass in the name of a single feature file as a testng parameter (using @Parameter) and run it. I'd like a runtime solution.

I have a bunch of non-Cucumber tests using already written using the TestNG framework and I'd like to have the Cucumber code in there as well.

Has anyone come up with something clever ?


Answer:

Figured out how you can send custom cucumberoptions which contains the feature file name to the runner class. This will allow both cucumber and non-cucumber tests to be run from testng.xml.

Below text is based on details in "Cucumber for Java" book...


Cucumber checks if any option overrides have been provided for @CucumberOptions annotation. Following are checked from top to bottom, stops after any one is found:

  1. The OS environment variable CUCUMBER_OPTIONS
  2. The Java system property cucumber.options
  3. The Java resource bundle cucumber.properties with a cucumber.options property

Values found in override will replace any values set except for the plugin argument. Plugin argument will be appended. Arguments which are not overridden will not be affected.


testng.xml

<suite name="Default suite">    
    <test name="Cucumber Mix">
        <classes>
            <class name="cucumtestng.test.RunAbstractSampleTest"></class>
            <class name="cucumtestng.test.NormalTest"></class>
        </classes>
    </test>
</suite>


@CucumberOptions(features="",glue="cucumtestng.test.stepdefs",snippets=SnippetType.CAMELCASE,
plugin={"pretty", "html:report", "json:reports.json"})
public class RunAbstractSampleTest extends AbstractTestNGCucumberTests {

}


public class NormalTest {
  @Test
  public void f() {
      System.out.println("NORMAL TESTNG CLASS");
  }
}

You can also use testng cucumber classes which do not extend AbstractTestNgCucumberTests but use composition...

Setup Run As Configuration in eclipse as below and run...

Question:

Cucumber not executing both the features with created stepdefinations

I have tried with tag, also given both full path of both the features but still the same

package runners;

import com.cucumber.listener.ExtentProperties;
import com.cucumber.listener.Reporter;
import cucumber.api.CucumberOptions;
import cucumber.api.junit.Cucumber;
import managers.Common;
import managers.FileReader;
import org.apache.log4j.PropertyConfigurator;
import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.runner.RunWith;
import java.io.File;

@RunWith(Cucumber.class)
@CucumberOptions(
        features = ".//src//test//java//FeatureList",glue = "stepDefinations",
        plugin = { "com.cucumber.listener.ExtentCucumberFormatter:",
                "junit:target/cucumber-results.xml"},
        tags={"@API"},
        monochrome = true
)
public class TestRunner {

    static String ReportName= Common.ReportName();

    @BeforeClass
    public static void setup() {

        ExtentProperties extentProperties = ExtentProperties.INSTANCE;
        extentProperties.setReportPath("target/cucumber-reports/"+ReportName+".html");
        PropertyConfigurator.configure(".//src//log4j.properties");
    }

    @AfterClass
    public static void writeExtentReport() {

        Reporter.loadXMLConfig(new File(FileReader.getInstance().getConfigReader().getReportConfigPath()));
        Reporter.setSystemInfo("User Name", System.getProperty("user.name"));
        Reporter.setSystemInfo("Time Zone", System.getProperty("user.timezone"));
        Reporter.setSystemInfo("Environment", FileReader.getInstance().getConfigReader().getEnvironment());
    }
}

Not sure why its always running error codes.feature but never enums.feature

Feature: Enums Codes @API Scenario: xxx Enums Codes Given Run get method "xxxxxxxxxxx" api to get fetch all type of xxx xxx Then response should be 200 And xxxxxxxxxxxxxx

Feature: Error Codes

@API Scenario: xxError Codes Given Run "xxxx" api to get response Then response should be 200 And Verify xx Error Codes xx error response


Answer:

"features" is looking for a filesystem path:

features = ".//src//test//java//FeatureList"

Try this - 1 features = "src/test/java/FeatureList" 2 features = "FeatureList"

Question:

Building up on this question, the example provided seems to lock the text in the feature file too much to Java programming style (notice that the text is written in all uppercase, and is only one word.

Is it possible to pass enums when the feature file has more "human readable" text? E.g.:

Simple Example

Feature: Setup Enum and Print value
  In order to manage my Enum
  As a System Admin
  I want to get the Enum

  Scenario Outline: Verify Enum Print
  When I supply a more human readable text to be converted to <Enum>

  Examples: Text can have multiple formats
  |Enum         |
  |Christmas    |
  |New Year Eve |
  |independence-day|

I reckon the enum could be something like:

public enum Holiday {

CHRISTMAS("Christmas"),NEW_YEAR("New Year"),INDEPENDENCE_DAY("independence-day");

private String extendedName;

private Holidays(String extendedName) {
    this.extendedName = extendedName;
}

}

How could we convert one from the other?

More complex example

In a more complex example, we would pass this onto a ScenarioObject

Scenario: Enum within a Scenario Object
      When I supply a more human readable text to be converted in the objects: 
      |Holiday         |Character|
      |Christmas    |Santa  |
      |New Year Eve |Harry|
      |independence-day|John Adams|

public class ScenarioObject{
private String character;
private Holiday holiday;
(...getters and setters)
}

Update: If the only solution is to apply a Transformer, as described here, an example of how this would be a applied to the ScenarioObject would be appreciated, since simply tagging the enum with a @XStreamConverter(HolidayTransformer.class) is not sufficient for the transformer to work within the ScenarioObject.


Answer:

The best solution I found for this so far was with a transformer. In the case of the complex example with ScenarioObject,this involves:

Mark enum with converter

@XStreamConverter(HolidayTransformer.class)
public enum Holiday {

CHRISTMAS("Christmas"),NEW_YEAR("New Year"),INDEPENDENCE_DAY("independence-day");

private String extendedName;

private Holidays(String extendedName) {
this.extendedName = extendedName;
}

public static Holiday fromString(String type) throws Exception {...}
}

Create the transformer

public class HolidayTransformer  extends Transformer<Holiday> {

@Override
public Holiday transform(String value) {
    try {
        return Holiday.fromString(value);
    } catch (Exception e) {
        fail("Could not convert from value");
        return null;
    }
}

}

Mark the ScenarioObject with the transformer as well

public class ScenarioObject{
private String character;
@XStreamConverter(HolidayTransformer.class)
private Holiday holiday;
(...getters and setters)
}

Question:

I'm using Karate for testing REST API, now I'm trying to run feature files in parallel:

@CucumberOptions(tags = { "@someTest" })
public class ParallelTest {

@Test
public void testParallel() {
    KarateStats stats = CucumberRunner.parallel(getClass(), 5, 
    "target/surefire-reports/cucumber-html-reports");
    Assert.assertTrue(stats.getFailCount() == 0, "scenarios failed");
   }
}

The test runs only 3 feature files in parallel and doesn't run all 5 features. I got this code from CucumberRunner.parallel function:

CucumberRunner runner = new CucumberRunner(this.getClass());
List<FeatureFile> featureFiles = runner.getFeatureFiles();

Then tried to load my feature files, the list size is 3, that means the function didn't load all features. Any idea why this is happening?

Note: all feature files under the same package.

Parallel() function code:

  public static KarateStats parallel(Class clazz, int threadCount, String reportDir) {
    KarateStats stats = KarateStats.startTimer();
    ExecutorService executor = Executors.newFixedThreadPool(threadCount);
    CucumberRunner runner = new CucumberRunner(clazz);
    List<FeatureFile> featureFiles = runner.getFeatureFiles();
    List<Callable<KarateJunitFormatter>> callables = new ArrayList<>(featureFiles.size());
    int count = featureFiles.size();
    for (int i = 0; i < count; i++) {
        int index = i + 1;
        FeatureFile featureFile = featureFiles.get(i);
        callables.add(() -> {
            String threadName = Thread.currentThread().getName();
            KarateJunitFormatter formatter = getFormatter(reportDir, featureFile);
            logger.info(">>>> feature {} of {} on thread {}: {}", index, count, threadName, featureFile.feature.getPath());
            runner.run(featureFile, formatter);
            logger.info("<<<< feature {} of {} on thread {}: {}", index, count, threadName, featureFile.feature.getPath());
            formatter.done();
            return formatter;
        });
    }
    try {
        List<Future<KarateJunitFormatter>> futures = executor.invokeAll(callables);
        stats.stopTimer();
        for (Future<KarateJunitFormatter> future : futures) {
            KarateJunitFormatter formatter = future.get();
            stats.addToTestCount(formatter.getTestCount());
            stats.addToFailCount(formatter.getFailCount());
            stats.addToSkipCount(formatter.getSkipCount());
            stats.addToTimeTaken(formatter.getTimeTaken());
            if (formatter.isFail()) {
                stats.addToFailedList(formatter.getFeaturePath());
            }
        }
        stats.printStats(threadCount);
        return stats;
    } catch (Exception e) {
        throw new RuntimeException(e);
    }
}

Thanks :)


Answer:

The simplest explanation is that the tags in the @CucumberOptions is having an effect. Try commenting it out and try again. Else there is nothing I can make out from the information you have provided.

Question:

I have a few Scenarios in a Feature file with repeatable steps ('I am on Login form' and 'click on login button'). Test failed with error Duplicate step definitions in Steps.LoginSteps. Is it possible to somehow to reuse duplicated steps?

Feature: LoginFeature

Scenario: Login with valid username and password
    Given I am on Login form
    And I enter valid username and password
    And click on login button
    Then I should see the main page


  Scenario: Login with invalid username and password
    Given  I am on Login form
    And I enter invalid email username and password
    And click on login button
    When modal error is displayed
    Then click on Ok button
    And I should see the login form 

Answer:

All steps are global and Cucumber will use the method with a matching regular expression.

The logic behind this is that if you use one way of describing your desired behaviour in two or more places, how can you expect this behaviour to be different in in different scenarios?

You give a perfect example with your login step. Do you expect to be on different login pages just because you are planning to verify a positive and a negative case? The answer is obviously no and therefore there is no need for more than one step implementation.

Next thing you might find is an urge to call a step from another step. Don't do that. Create a helper method that both steps call in this situation.

I try to keep my steps really short, one or two lines in most cases. I usually just delegate to a helper directly. This allows me to change abstraction level and go from translating arguments to a step to interacting with the system under test.

Question:

I am integrating a cucumber-java with an existing gradle java project, that has a focus on test automation. There is no production code within this project, so making the entire project makes little sense.

What I would like to do is to create gradle tasks or a single gradle task with a -D property that specifies a cucumber .feature file to run cucumber-jvm on. All of the examples that I've seen show how to get cucumber-jvm to run as part of the build process. Instead, I would like to define a task testCucumber(type: Test) to run a single .feature file. How would I go about doing this?


Answer:

I was able to get this to work by using a javaexec task in gradle.

 javaexec {
        main = "cucumber.api.cli.Main"
        classpath = configurations.cucumberRuntime + sourceSets.main.output + sourceSets.test.output
        args = ['--plugin', 'junit:target/cucumber-junit-report.xml', '--plugin', 'pretty', '--glue', 'StepDefinitions', 'src/test/Features/FeatureFilename.feature']
    }

This is assuming that all step definitions are defined within a package called "StepDefinitions".

Question:

Intellij is saying my step is undefined when I'm looking at the .feature file.

Intellij undefined step

But the cucumber .feature file runs fine, and it is definitely matching on the step.

My TestNG runner code:

package package1;

import io.cucumber.testng.AbstractTestNGCucumberTests;
import io.cucumber.testng.CucumberOptions;
import org.testng.annotations.DataProvider;

@CucumberOptions(plugin = "pretty", features = "src/test/resources/package1", glue = "package1")
public class Runner extends AbstractTestNGCucumberTests {

    @Override
    @DataProvider(parallel = true)
    public Object[][] scenarios() {
        return super.scenarios();
    }

}

The step in the feature file:

Feature: test feature
  Scenario: test feature scenario
  Given there has been a pebkac

My step in the StepDefinitions file:

Given("there has been a pebkac", () -> {
            //driver.findElement(By.id("editTextFieldId")).sendKeys("test");
            autoTools.getElement(new String[]{"editTextFieldId", "IOSIDHERE"}, AutomationTools.IdType.DEFAULT, 15).sendKeys("test");
            System.out.format("test: %n\n");

            //throw new cucumber.api.PendingException();
        });

Why is intellij complaining that it can't find this step? I tried using the step definition file with annotations instead and ran into the same issue.

I notice though that if I go to the feature file and right click -> add step, it will add a step using a deprecated Given method. This makes me feel like I may be using the wrong dependencies, though I got them from the cucumber tutorial on their website.

My dependencies:

dependencies {
    testImplementation 'io.cucumber:cucumber-java:4.7.4'

    compile group: 'org.testng', name: 'testng', version: '6.14.3'
    compile group: 'io.cucumber', name: 'cucumber-testng', version: '4.7.4'
    compile group: 'io.appium', name: 'java-client', version: '7.1.0'
}


Answer:

Intellij was out of date, updating it resolved this problem.

Reference: https://sqa.stackexchange.com/q/40044

Question:

I need some help with running a feature file.

This is the skeleton of the Maven project:

This is my pom.xml file:

 <properties>
    <maven.compiler.source>1.8</maven.compiler.source>
    <maven.compiler.target>1.8</maven.compiler.target>
    <junit.version>5.0.0</junit.version>
    <selenium.version>3.4.0</selenium.version>
    <surefire.version>2.12.4</surefire.version>
    <slf4j.version>1.7.25</slf4j.version>
    <log4j.version>2.9.1</log4j.version>
    <testng.version>6.11</testng.version>
    <apache.poi.version>3.16</apache.poi.version>
</properties>

<dependencies>
    <dependency>
        <groupId>org.seleniumhq.selenium</groupId>
        <artifactId>selenium-java</artifactId>
        <version>${selenium.version}</version>
    </dependency>
    <dependency>
        <groupId>junit</groupId>
        <artifactId>junit</artifactId>
        <version>4.12</version>
        <scope>test</scope>
    </dependency>
    <dependency>
        <groupId>org.slf4j</groupId>
        <artifactId>slf4j-api</artifactId>
        <version>${slf4j.version}</version>
    </dependency>
    <dependency>
        <groupId>org.seleniumhq.selenium</groupId>
        <artifactId>selenium-chrome-driver</artifactId>
        <version>${selenium.version}</version>
    </dependency>
    <dependency>
        <groupId>org.seleniumhq.selenium</groupId>
        <artifactId>selenium-remote-driver</artifactId>
        <version>${selenium.version}</version>
    </dependency>
    <dependency>
        <groupId>org.seleniumhq.selenium</groupId>
        <artifactId>selenium-firefox-driver</artifactId>
        <version>${selenium.version}</version>
    </dependency>
    <dependency>
        <groupId>org.seleniumhq.selenium</groupId>
        <artifactId>selenium-server</artifactId>
        <version>${selenium.version}</version>
    </dependency>
    <dependency>
        <groupId>org.seleniumhq.selenium</groupId>
        <artifactId>selenium-ie-driver</artifactId>
        <version>${selenium.version}</version>
    </dependency>
    <dependency>
        <groupId>org.seleniumhq.selenium</groupId>
        <artifactId>selenium-edge-driver</artifactId>
        <version>${selenium.version}</version>
    </dependency>
    <dependency>
        <groupId>org.seleniumhq.selenium</groupId>
        <artifactId>selenium-opera-driver</artifactId>
        <version>${selenium.version}</version>
    </dependency>
    <dependency>
        <groupId>org.seleniumhq.selenium</groupId>
        <artifactId>selenium-safari-driver</artifactId>
        <version>${selenium.version}</version>
    </dependency>
    <dependency>
        <groupId>org.apache.poi</groupId>
        <artifactId>poi</artifactId>
        <version>${apache.poi.version}</version>
    </dependency>
    <dependency>
        <groupId>org.apache.logging.log4j</groupId>
        <artifactId>log4j-core</artifactId>
        <version>${log4j.version}</version>
    </dependency>
    <dependency>
        <groupId>org.apache.logging.log4j</groupId>
        <artifactId>log4j-api</artifactId>
        <version>${log4j.version}</version>
    </dependency>
    <dependency>
        <groupId>org.apache.poi</groupId>
        <artifactId>poi-ooxml</artifactId>
        <version>${apache.poi.version}</version>
    </dependency>
    <dependency>
        <groupId>org.testng</groupId>
        <artifactId>testng</artifactId>
        <version>${testng.version}</version>
        <scope>test</scope>
    </dependency>
    <dependency>
        <groupId>io.appium</groupId>
        <artifactId>java-client</artifactId>
        <version>${appium.version}</version>
        <scope>test</scope>
    </dependency>
    <dependency>
        <groupId>info.cukes</groupId>
        <artifactId>cucumber-java</artifactId>
        <version>${cucumber.version}</version>
    </dependency>
    <dependency>
        <groupId>info.cukes</groupId>
        <artifactId>cucumber-junit</artifactId>
        <version>${cucumber.version}</version>
        <scope>test</scope>
    </dependency>
    <dependency>
        <groupId>info.cukes</groupId>
        <artifactId>gherkin</artifactId>
        <version>2.12.2</version>
    </dependency>
    <dependency>
        <groupId>info.cukes</groupId>
        <artifactId>cucumber-java</artifactId>
        <version>${cucumber.version}</version>
        <scope>test</scope>
    </dependency>
    <dependency>
        <groupId>info.cukes</groupId>
        <artifactId>cucumber-junit</artifactId>
        <version>${cucumber.version}</version>
        <scope>test</scope>
    </dependency>
    <dependency>
        <groupId>info.cukes</groupId>
        <artifactId>cucumber-core</artifactId>
        <version>1.2.5</version>
        <scope>test</scope>
    </dependency>
    <dependency>
        <groupId>info.cukes</groupId>
        <artifactId>cucumber-java</artifactId>
        <version>1.2.5</version>
        <scope>test</scope>
    </dependency>
    <dependency>
        <groupId>info.cukes</groupId>
        <artifactId>cucumber-junit</artifactId>
        <version>1.2.5</version>
        <scope>test</scope>
    </dependency>
    <dependency>
        <groupId>com.github.stephenc.monte</groupId>
        <artifactId>monte-screen-recorder</artifactId>
        <version>0.7.7.0</version>
    </dependency>
    <dependency>
        <groupId>io.cucumber</groupId>
        <artifactId>cucumber-java</artifactId>
        <version>3.0.0</version>
        <scope>test</scope>
    </dependency>
    <dependency>
        <groupId>info.cukes</groupId>
        <artifactId>cucumber-jvm</artifactId>
        <version>1.0.11</version>
        <type>pom</type>
    </dependency>
    <dependency>
        <groupId>info.cukes</groupId>
        <artifactId>cucumber-java8</artifactId>
        <version>1.2.5</version>
        <scope>test</scope>
    </dependency>

</dependencies>
<build>
    <plugins>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-surefire-plugin</artifactId>
            <version>${surefire.version}</version>
            <configuration>
                <skipTests>true</skipTests>
            </configuration>
        </plugin>
    </plugins>
</build>

And, when I try to run my Feature file, the error is below:

Exception in thread "main" cucumber.runtime.CucumberException: Unrecognized plugin: org.jetbrains.plugins.cucumber.java.run.CucumberJvm2SMFormatter
at cucumber.runtime.RuntimeOptions$ParsedPluginData.addPluginName(RuntimeOptions.java:372)
at cucumber.runtime.RuntimeOptions.parse(RuntimeOptions.java:125)
at cucumber.runtime.RuntimeOptions.<init>(RuntimeOptions.java:85)
at cucumber.runtime.RuntimeOptions.<init>(RuntimeOptions.java:78)
at cucumber.runtime.RuntimeOptions.<init>(RuntimeOptions.java:70)
at cucumber.api.cli.Main.run(Main.java:31)
at cucumber.api.cli.Main.main(Main.java:18)

Process finished with exit code 1

My java version is:

java version "1.7.0_79" Java(TM) SE Runtime Environment (build 1.7.0_79-b15) Java HotSpot(TM) 64-Bit Server VM (build 24.79-b02, mixed mode)

This is my RUN/Debug configuration:

I'm not able to run the Feature file and with this, I cannot run any related with Cucumber. Can you please help me?

Thanks in advance.


Answer:

Several things:

  1. Remove duplicate dependencies

  2. Make sure you are using the same Cucumber version for all Cucumber dependencies. Otherwise, Cucumber might behave unexpectedly. It's helpful to use a version number like this <version>${cucumber.version}</version> for each dependency, so you can update it in one place and are sure all dependencies are using the same version (note that you are using this in several places, but I don't see the cucumber version defined anywhere).

  3. Update to a newer version of Cucumber; v1.2.5 is quite old at this point. Current version is 3.0.2. Note: <groupId>info.cukes</groupId> was updated to <groupId>io.cucumber</groupId>

  4. Remove unnecessary dependencies; afaik cucumber-core and gherkin are not needed as they are transitive dependencies of other libraries.

Question:

Currently I'm using a testng.xml file to target a specific RunnerClass which would then target one or more feature files via Jenkins and in turn produce a detailed report.

Is there a way to target one feature file within Jenkins based on the name of the feature file? and in turn produce a report within Jenkins.


Answer:

I know we can run a single feature file by using cucumber.options which will override all the options you have in the @CucumberOptions annotation:

mvn test -Dcucumber.options="src/test/features/com/automation/organization/featurefiles/Account.feature"

I do not think so there is direct option available in Jenkins for running a single feature file. However You may need to identify how to execute above command from POM.xml so things get run by POM and then Jenkins.

Question:

i Have Try to run the Cucumber BDD Framework with Testng maven and i have done all the configurations to the setup but the problem is the feature file of Cucumber is not enabling. down i will post my code and pom.xml please guide me where and what i missed. :(

My Code for the runner class:

package org.cucumber.MRtests;

import io.github.bonigarcia.wdm.WebDriverManager;

import org.junit.BeforeClass;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;
import org.testng.annotations.AfterClass;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;

import cucumber.api.CucumberOptions;
import cucumber.api.testng.CucumberFeatureWrapper;
import cucumber.api.testng.TestNGCucumberRunner;


@CucumberOptions(features="src/test/resources/Features",glue={"org.cucumber.stepdefs"})
public class OpenMRTest 
{
    public static WebDriver driver;
    private TestNGCucumberRunner testRunner;


    @BeforeClass
    public void Setup()
    {
        WebDriverManager.chromedriver().setup();
        driver = new ChromeDriver();
        testRunner = new TestNGCucumberRunner(OpenMRTest.class);
    }

    @Test(description="login",dataProvider="features")
    public void login(CucumberFeatureWrapper cFeature)
    {
        testRunner.runCucumber(cFeature.getCucumberFeature());
    }

    @DataProvider(name="features")
    public Object[][] getFeatures()
    {
        return testRunner.provideFeatures();
    }
    @AfterClass
    public void tearDown()
    {
        testRunner.finish();
    }

}

My Code for the Declaring part:

package org.cucumber.stepdefs;


import org.cucumber.MRtests.OpenMRTest;
import org.openqa.selenium.By;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.support.ui.Sleeper;
import org.testng.Assert;

import cucumber.api.java.en.Given;
import cucumber.api.java.en.Then;
import cucumber.api.java.en.When;


public class LoginPage  
{
    @Given("^Open Application and Enter url$")
    public void open_Application_and_Enter_url() throws Throwable {
      OpenMRTest.driver.get("xxxxxxxxxxxxxxxxxxxxxxxxxxxx");

    }

    @When("^enter username$")
    public void enter_username() throws Throwable {

        OpenMRTest.driver.findElement(By.xpath("//a[text()='Log In']")).click();
        Sleep(5000);
        OpenMRTest.driver.findElement(By.id("email")).sendKeys("xxxxxxxxxxxxxxx");
    }

    private void Sleep(int i) throws InterruptedException {
        Thread.sleep(i);

    }

    @When("^enter password$")
    public void enter_password() throws Throwable {
        OpenMRTest.driver.findElement(By.id("password")).sendKeys("xxxxxxxxxxxxxxxxxx");
        OpenMRTest.driver.findElement(By.xpath("//button[@id='submit-button']")).click();
    }

    @Then("^verify Msg$")
    public void verify_Msg() throws Throwable {
       boolean result =  OpenMRTest.driver.findElement(By.xpath("//div[@class='grid']/h1")).getText().contains("Top Questions");
       Assert.assertTrue(result);
    }
}

My POM.XML File :

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>BDDFramework</groupId>
  <artifactId>BDDFramework</artifactId>
  <version>0.0.1-SNAPSHOT</version>
  <name>BDD</name>

<properties>
<suiteXmlFile>src/main/resources/testng.xml</suiteXmlFile>
</properties>



<dependencies>

<dependency>
    <groupId>org.testng</groupId>
    <artifactId>testng</artifactId>
    <version>6.14.3</version>
    <scope>test</scope>
</dependency>

<dependency>
    <groupId>junit</groupId>
    <artifactId>junit</artifactId>
    <version>4.12</version>
    <scope>test</scope>
</dependency>

<dependency>
<groupId>info.cukes</groupId>
<artifactId>cucumber-jvm-deps</artifactId>
<version>1.0.5</version>
<scope>provided</scope>
</dependency>

<dependency>
    <groupId>info.cukes</groupId>
    <artifactId>cucumber-junit</artifactId>
    <version>1.2.5</version>
    <scope>test</scope>
</dependency>


<dependency>
    <groupId>info.cukes</groupId>
    <artifactId>cucumber-java</artifactId>
    <version>1.2.5</version>

</dependency>


<dependency>
    <groupId>io.github.bonigarcia</groupId>
    <artifactId>webdrivermanager</artifactId>
    <version>3.0.0</version>
    <scope>test</scope>
</dependency>

<dependency>
    <groupId>org.seleniumhq.selenium</groupId>
    <artifactId>selenium-java</artifactId>
    <version>3.141.59</version>
</dependency>

<dependency>
    <groupId>info.cukes</groupId>
    <artifactId>cucumber-testng</artifactId>
    <version>1.2.5</version>
</dependency>




</dependencies>

  <build>
    <defaultGoal>install</defaultGoal>
  <plugins>

  <plugin>
  <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-compiler-plugin</artifactId>
    <version>3.8.0</version>
    </plugin>

    <plugin>
     <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-surefire-plugin</artifactId>
    <version>2.22.1</version>

    <configuration>

    <suiteXmlFiles>
<suiteXmlFile>${suiteXmlFile}</suiteXmlFile>
</suiteXmlFiles>
    </configuration>
      </plugin>

  </plugins>
  </build>
</project>

and Also i have attached the feature file how it is Looking. please guide me through this issue.

Exception is ::

[INFO] Running TestSuite
[Utils] [ERROR] [Error] java.lang.NullPointerException
    at org.cucumber.MRtests.OpenMRTest.getFeatures(OpenMRTest.java:41)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at org.testng.internal.MethodInvocationHelper.invokeMethod(MethodInvocationHelper.java:124)
    at org.testng.internal.MethodInvocationHelper.invokeMethod(MethodInvocationHelper.java:74)
    at org.testng.internal.MethodInvocationHelper.invokeMethodNoCheckedException(MethodInvocationHelper.java:45)
    at org.testng.internal.MethodInvocationHelper.invokeDataProvider(MethodInvocationHelper.java:131)
    at org.testng.internal.Parameters.handleParameters(Parameters.java:706)
    at org.testng.internal.ParameterHandler.handleParameters(ParameterHandler.java:49)
    at org.testng.internal.ParameterHandler.createParameters(ParameterHandler.java:37)
    at org.testng.internal.Invoker.invokeTestMethods(Invoker.java:924)
    at org.testng.internal.TestMethodWorker.invokeTestMethods(TestMethodWorker.java:125)
    at org.testng.internal.TestMethodWorker.run(TestMethodWorker.java:109)
    at org.testng.TestRunner.privateRun(TestRunner.java:648)
    at org.testng.TestRunner.run(TestRunner.java:505)
    at org.testng.SuiteRunner.runTest(SuiteRunner.java:455)
    at org.testng.SuiteRunner.runSequentially(SuiteRunner.java:450)
    at org.testng.SuiteRunner.privateRun(SuiteRunner.java:415)
    at org.testng.SuiteRunner.run(SuiteRunner.java:364)
    at org.testng.SuiteRunnerWorker.runSuite(SuiteRunnerWorker.java:52)
    at org.testng.SuiteRunnerWorker.run(SuiteRunnerWorker.java:84)
    at org.testng.TestNG.runSuitesSequentially(TestNG.java:1208)
    at org.testng.TestNG.runSuitesLocally(TestNG.java:1137)
    at org.testng.TestNG.runSuites(TestNG.java:1049)
    at org.testng.TestNG.run(TestNG.java:1017)
    at org.apache.maven.surefire.testng.TestNGExecutor.run(TestNGExecutor.java:283)
    at org.apache.maven.surefire.testng.TestNGXmlTestSuite.execute(TestNGXmlTestSuite.java:75)
    at org.apache.maven.surefire.testng.TestNGProvider.invoke(TestNGProvider.java:120)
    at org.apache.maven.surefire.booter.ForkedBooter.invokeProviderInSameClassLoader(ForkedBooter.java:384)
    at org.apache.maven.surefire.booter.ForkedBooter.runSuitesInProcess(ForkedBooter.java:345)
    at org.apache.maven.surefire.booter.ForkedBooter.execute(ForkedBooter.java:126)
    at org.apache.maven.surefire.booter.ForkedBooter.main(ForkedBooter.java:418)

[ERROR] Tests run: 2, Failures: 1, Errors: 0, Skipped: 1, Time elapsed: 0.591 s <<< FAILURE! - in TestSuite
[ERROR] tearDown(org.cucumber.MRtests.OpenMRTest)  Time elapsed: 0.448 s  <<< FAILURE!
java.lang.NullPointerException
    at org.cucumber.MRtests.OpenMRTest.tearDown(OpenMRTest.java:46)

[INFO] 
[INFO] Results:
[INFO] 
[ERROR] Failures: 
[ERROR]   OpenMRTest.tearDown:46 NullPointer
[INFO] 
http://cwiki.apache.org/confluence/display/MAVEN/MojoFailureException

Answer:

I think you are not plugin cucumber in Eclipse

Please Install Cucumber Eclipse plugin

1) Launch the Eclipse IDE and from Help menu, click "Install New Software".

2) You will see a dialog window, click "Add" button.

3) Type name as you wish, let’s take "Cucumber" and type "http://cucumber.github.com/cucumber-eclipse/update-site" as location. Click OK.

4) You come back to the previous window but this time you must see Cucumber Eclipse Plugin option in the available software list. Just Check the box and press "Next button.

5) Click on Next.

6) Click "I accept the terms of the license agreement" then click Finish.

7) Let it install, it will take few seconds to complete.

8) You may or may not encounter a Security warning, if in case you do just click OK.

9) You are all done now, just Click Yes.

Question:

i am trying to print the output written in the step definitions into eclipse console. but i do not see any output in the console

i have added these below dependencies into my project and i have also included "pretty" and monochrome :true in the runner class

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>

  <groupId>sampleProject</groupId>
  <artifactId>sampleProject</artifactId>
  <version>0.0.1-SNAPSHOT</version>
  <packaging>jar</packaging>

  <name>sampleProject</name>
  <url>http://maven.apache.org</url>

  <properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
  </properties>

    <build>
    <pluginManagement>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.8.1</version>
                <configuration>
                    <source>1.7</source>
                    <target>1.7</target>
                </configuration>
            </plugin>
        </plugins>

    </pluginManagement>
</build>

  <dependencies>
        <!-- https://mvnrepository.com/artifact/io.cucumber/cucumber-core -->
    <dependency>
        <groupId>io.cucumber</groupId>    
        <artifactId>cucumber-core</artifactId>
        <version>4.7.1</version>
    </dependency>

    <!-- https://mvnrepository.com/artifact/org.apache.maven.plugins/maven-compiler-plugin -->
    <dependency>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-compiler-plugin</artifactId>
        <version>3.8.1</version>
    </dependency>


    <dependency>  
          <groupId>com.sun</groupId> 
           <artifactId>tools</artifactId>
        <version>1.8</version>
        <scope>system</scope>
        <systemPath>${java.home}\lib\tools-1.8.0.jar</systemPath>
     </dependency> 

    <dependency>
    <groupId>io.cucumber</groupId>
    <artifactId>cucumber-junit</artifactId>
    <version>4.7.1</version>
    <scope>test</scope>
    </dependency>

      <dependency>
    <groupId>io.cucumber</groupId>
    <artifactId>cucumber-java</artifactId>
    <version>4.7.1</version>
    </dependency>

    <dependency>
    <groupId>net.sourceforge.cobertura</groupId>
    <artifactId>cobertura</artifactId>
    <version>2.1.1</version>
    <scope>test</scope>
    </dependency>

    <dependency>
    <groupId>net.masterthought</groupId>
    <artifactId>cucumber-reporting</artifactId>
    <version>4.8.0</version>
    </dependency>

    <dependency>
    <groupId>io.cucumber</groupId>
    <artifactId>cucumber-jvm-deps</artifactId>
    <version>1.0.6</version>
    <scope>provided</scope>
    </dependency>

        <!-- https://mvnrepository.com/artifact/io.cucumber/cucumber-jvm -->
     <dependency>
        <groupId>io.cucumber</groupId>
        <artifactId>cucumber-jvm</artifactId>
        <version>4.7.1</version>
        <type>pom</type>
    </dependency> 

        <!-- https://mvnrepository.com/artifact/log4j/log4j -->
    <dependency>
        <groupId>log4j</groupId>
        <artifactId>log4j</artifactId>
        <version>1.2.17</version>
    </dependency>


    <dependency>
    <groupId>org.mockito</groupId>
    <artifactId>mockito-all</artifactId>
    <version>1.10.19</version>
    <scope>test</scope>
    </dependency>

    <dependency>
    <groupId>org.seleniumhq.selenium</groupId>
    <artifactId>selenium-java</artifactId>
    <version>3.141.59</version>
    </dependency>

      <dependency>
    <groupId>io.cucumber</groupId>
    <artifactId>gherkin</artifactId>
    <version>5.1.0</version>
    </dependency>

    <dependency>
    <groupId>io.cucumber</groupId>
    <artifactId>cucumber-html</artifactId>
    <version>0.2.7</version>
    </dependency>

    <!-- https://mvnrepository.com/artifact/junit/junit-dep -->
    <dependency>
        <groupId>junit</groupId>
        <artifactId>junit-dep</artifactId>
        <version>4.11</version>
        <type>pom</type>
        <scope>test</scope>
    </dependency>

    <!-- https://mvnrepository.com/artifact/org.testng/testng -->
    <dependency>
        <groupId>org.testng</groupId>
        <artifactId>testng</artifactId>
        <version>6.14.3</version>
        <scope>compile</scope>
    </dependency>

    <!-- https://mvnrepository.com/artifact/io.cucumber/cucumber-testng -->
    <dependency>
        <groupId>io.cucumber</groupId>
        <artifactId>cucumber-testng</artifactId>
        <version>4.7.1</version>
    </dependency>


  </dependencies>
</project>

for example if i print any thing in my step definitions like System.out.println("2+2");

when i ran this code, only see the below lines in the console

 [RemoteTestNG] detected TestNG version 6.14.3
Starting ChromeDriver 76.0.3809.68 (420c9498db8ce8fcd190a954d51297672c1515d5-refs/branch-heads/3809@{#864}) on port 9315
Only local connections are allowed.
Please protect ports used by ChromeDriver and related test frameworks to prevent access by malicious code.
Aug 02, 2019 11:54:35 AM org.openqa.selenium.remote.ProtocolHandshake createSession
INFO: Detected dialect: W3C
Feature: Check addition in Google calculatorcontent
   In order to verify that Google calculator work correctly
   As a user of Google
   I should be able to get correct addition result

  Scenario: Addition                     # src/main/java/Features/sample.feature:6
    Given I open Google                  # SampleStepDef.I_open_google()
    When I enter "2+2" in search textbox # SampleStepDef.I_enter_in_search_textbox(String)
    Then I should get result as "4"      # SampleStepDef.I_should_get_correct_result(String)
PASSED: runScenario("Addition", "Check addition in Google calculatorcontent")
        Runs Cucumber Scenarios

===============================================

the console does not display anything else other than this.

it also does not display the number of scenarios and steps passed or failed like

1 Scenarios ([33m1 undefined[0m)
   3 Steps ([33m3 undefined[0m)
   0m0.000s

And here is my tesRunner code package Runner;

import io.cucumber.testng.AbstractTestNGCucumberTests;
import io.cucumber.testng.CucumberOptions;

@CucumberOptions(
        features = "src/main/java/Features",
        glue = {"StepDefinitions"},
       // tags = "@SmokeTest",
        monochrome = true,
        dryRun = false,
        strict = true,
        plugin = {
                "pretty",
                "html:target/cucumber-reports/cucumber-pretty",
                "json:target/cucumber-reports/CucumberTestReport.json",
                "rerun:target/cucumber-reports/rerun.txt"
        }
        )

public class TestRunner extends AbstractTestNGCucumberTests {


}

and stepDefifnition code

package StepDefinitions;


import java.util.concurrent.TimeUnit;

import org.testng.Assert;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.firefox.FirefoxDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.By;

import io.cucumber.java.After;
import io.cucumber.java.Before;
import org.apache.log4j.Logger;

import org.apache.log4j.xml.DOMConfigurator;
import io.cucumber.java.en.Given;
import io.cucumber.java.en.Then;
import io.cucumber.java.en.When;
public class SampleStepDef {


    protected WebDriver driver;
     private static Logger Log = Logger.getLogger(Logger.class.getName());
     @Before
        public void setup() {
        System.setProperty("webdriver.chrome.driver","C:\\Users\\Admin\\Downloads\\chromedriver.exe");
            driver = new ChromeDriver();
    }

    @Given("^I open Google$")
    public void I_open_google() {
        //Set implicit wait of 10 seconds and launch google

        driver.manage().timeouts().implicitlyWait(5, TimeUnit.SECONDS);
        driver.get("https://www.google.co.in");
    }

    @When("^I enter \"([^\"]*)\" in search textbox$")
    public void I_enter_in_search_textbox(String additionTerms) {
        //Write term in google textbox
        WebElement googleTextBox = driver.findElement(By.id("gbqfq"));
        googleTextBox.sendKeys(additionTerms);

        //Click on searchButton
        WebElement searchButton = driver.findElement(By.id("gbqfb"));
        searchButton.click();
    }

    @Then("^I should get result as \"([^\"]*)\"$")
    public void I_should_get_correct_result(String expectedResult) {
        //Get result from calculator
        WebElement calculatorTextBox = driver.findElement(By.id("cwos"));
        String result = calculatorTextBox.getText();

        //Verify that result of 2+2 is 4
        Assert.assertEquals(result, expectedResult);

        driver.close();
    }

     @After
        public void closeBrowser() {
            driver.quit();
     }

}

Answer:

With cucumber-jvm 4.5.0 and up, in order to see the summary statistics at the end of a run you need to explicit ask for it via the plugins you define in your runner class. If you add the "summary" (as you have already "pretty") you should be able to see again the totals of Scenarios/Steps and time it took. This has changed via https://github.com/cucumber/cucumber-jvm/pull/1670

Question:

I am having trouble on writing the feature file as I currently wanted to have multiple step definitions on each scenario. Here is my feature file:

Feature: Add new voucher
   As a user I want to be able to add vouchers

Scenario Outline: Add new voucher with an invalid voucher
    Given a trip voucher <Voucher>
    When I access "/voucher" endpoint
    Then error message should be "Voucher is invalid"

Examples:
  |Voucher    |
  |ABCDEFG    |
  |1234567    |
  |invaL!Ds   |

Scenario Outline: Add a previously redeemed voucher
    Given a used voucher <Voucher>
    When I access "/voucher" endpoint
   Then error message should be "Voucher has already been used"

Examples:
  |Voucher        |
  |VALIDVOUCHER   |

I am working on building a REST API on Go, while learning to create integration tests on Java because the QAs are using for testing. What is the best practice here on line When I access x endpoint? I know it will produce the Duplicate step definition error. Should I change how I wrote the feature file, or there are Java tricks that I am missing out.


Answer:

I am using SpecFlow + .NET at the moment at work and I have also used jBehave+Java in the past.

What you are doing is completely fine and it should not give you any errors. In fact, one of the advantage of having such Given-When-Then framework is to be able to reuse the phrases.

What you need to be careful about is to make sure that your step : When I access "/voucher" endpoint: should map to only one Java method in the steps file. so, something like:

@When("I access "/voucher" endpoint")
public void WhenIAccessVoucherEndpoint(){
// implementation of your step. may be make a Rest call.  
}

So, each time you refer to this step in your scenario file, the framework will always call this method for you. this way, you will have built basic building blocks (or pages if you are testing a website with page object pattern) and phrases. so, writing more scenarios will become easier and easier as it will be only a matter of finding the right phrases that are implemented and see if they can be reused.

Question:

I created a multi-modul maven project. After I implemented and (manually) tested a prototype I'm confident about the business model and want to improve and expand the functionality. Because of the high complexity I do want to ensure the quality of my project with BDD.

This is a representative structure for my project:

|restaurant
   |-kitchen
      |-src
         |-main
         |-test
            |-resources
                prepareStarter.feature
                prepareFood.feature
                prepareDesert.feature
   |-management
      |-src
         |-main
         |-test
            |-resources
                calculateProfit.feature
                prepareWorkSchedule.feature
   |-eatingroom
      |-src
         |-main
         |-test
            |-resources
                welcomeGuests.feature
                serveFood.feature
                serveDrinks.feature
   |-pom.xml

When I want to write a feature to ensure the integration of all three (example) projects, where do I put the feature file?

At the moment my Restaurant project is packaging as pom. Do I have to change it to java and put the feature files in |-restaurant|-src|-test|-resources?


Answer:

I think it would be better to keep your high level project as a pom module. It's very common in multi-module project to have a dedicated module containing only integration tests which covers cross module scenarios. I think the same applies to your project and the BDD features. By doing so your project structure would be something like this:

|restaurant
   |-kitchen
      |-src
         |-main
         |-test
            |-resources
                prepareStarter.feature
                prepareFood.feature
                prepareDesert.feature
   |-management
      |-src
         |-main
         |-test
            |-resources
                calculateProfit.feature
                prepareWorkSchedule.feature
   |-eatingroom
      |-src
         |-main
         |-test
            |-resources
                welcomeGuests.feature
                serveFood.feature
                serveDrinks.feature
   |-bdd-tests
      |-src
         |-main
         |-test
            |-resources
                cross-module-1.feature
                cross-module-2.feature
                cross-module-3.feature
   |-pom.xml

It's up to you to decide if you need to have a single module containing all integration and BDD tests together or a dedicated module for each type of tests. It depends on how many tests/features you have.

Question:

What I want is:

Then verify the following search task summery:
  | list of objects                                       | more columns... |
  | {property1: 1, property2: "hi", property3: true}, {property1: 1, property2: "hi", property3: true}              | .... |

Answer:

I did some research and although I haven't used such objects inside a .feature file below are a few things you could try if you haven't already.

A few things you could try:

  • If you really want to use that list and there is no other way, just handle it in the step definition as a String and change it however you want. Check out this link
  • Make the data table different again manage it in the step definition. An example would be:

Then verify the following search task summery:

| Property1 | Property2 | Property3 |
| 1         | hi        | true      |
| 2         | hello     | false     |

Have a look here and here for more details on this subject.

There might be different ways to do this and I hope this helps!

Question:

the question is it possible to run scenarios in custom order:

Imagine that we have 2 feature files (1st - to place an orders, 2nd is to create data for orders on the Back End side) In the first file I have scenarios with voucher code or without, so basically those scenarios that have to be triggered with voucher code should be triggered after back end (create voucher scenario is triggered). I expected to see the same behavior as we have for TestNG - dependsOnMethods. Is it possible to do for Cucumber ?

Thanks a lot.


Answer:

I would avoid coupling features as you suggest as much as possible.

Your first feature is about creating data and validating that the creation process is correct.

Your second feature is about working with data that you expect are available in the system.

My approach would be to have support code that create the data for each scenario when needed. This support code would setup the system in the expected state before any execution.

This might lead to duplication. Personally I would accept duplication in favour for readability. This would also introduce flexibility in this case. The coupled executions you are asking for will force you to execute everything every time. You would not ba able to execute a single scenario easily when trouble shooting.

BDD and Cucumber is all about human readable communication.

Clarity trumps DRY.

Question:

I need to run test for Android and iOS. I have one feature file for 2 platforms, because steps are the same. And different steps definitions files and page object files, separate for Android and iOS. How I can run one feature file only for Android/iOS and together for both.


Answer:

With the different step definition files it look like it is impossible.

In my current framework, I'm passing system properties while executing maven command, and getting that properties in step definition(isIos() method checks device parameter i passed), after that i'm calling the actual method. In this framework, all step definitions are same for iOS and Android application which makes this method reasonable. But also for this method you should initialize all your page objects in the beginning of execution.(I'm not injecting dependencies, initializing them at the beginning, then injecting drivers to them in step definition files)

@Then("The user clicks add to basket button")
public void theUserClicksAddToBasketButton() {
    try {
        if (Hooks.isIos()) {
            iosHomePage.clickAddToBasket();
        } else {
            androidHomePage.clickAddToBasket();
        }
        logger.info("The user clicked add to basket button");
    } catch (Throwable err) {
        logger.fatal("The user can not clicks add to basket button");
        Assert.fail("ERROR : " + "The user can not clicks add to basket button" + err);
    }
}

Question:

feature file ignore the Steps Definition and ignored Test

Issue :

The steps are defined and I can navigate to them through feature file but when i run it, it ignore the steps and suggest "You can implement missing steps with the snippets below:"

Can someone please have a look and kindly provide your feedback as i am not able to workout the problem?

[


Answer:

Finally i found the answer of this issue.

In the Runner Class, With GLUE instead of giving full path, if you give just Package name than it pick up the steps.

Question:

So I need to get the test step descriptions after the gherkin syntax

Feature: User trades stocks   Scenario: User requests a sell before close of trading
Given I have 100 shares of MSFT stock
   And I have 150 shares of APPL stock
   And the time is before close of trading

So what I really need is to get the

I have 100 shares of MSFT stock

I have 150 shares of APPL stock

the time is before close of trading

I found these as I update the cucumber to v5.0.0-RC1:

Can someone help me with a snippet? What is the object that needs to be passed to the AfterStep and BeforeStep?


Answer:

This is the code solution (in serviceHook class) for cucumber v4.3.1.

PickleStepTestStep currentStep;
private int counter = 0;

@BeforeStep
public void getStepName(Scenario scenario) throws Exception {

    Field f = scenario.getClass().getDeclaredField("testCase");
    f.setAccessible(true);
    TestCase r = (TestCase) f.get(scenario);

    List<PickleStepTestStep> stepDefs = r.getTestSteps()
            .stream()
            .filter(x -> x instanceof PickleStepTestStep)
            .map(x -> (PickleStepTestStep) x)
            .collect(Collectors.toList());

    currentStep = stepDefs.get(counter);

        System.out.println(currentStep.getStepText());

    }

@AfterStep
public void afterStep(Scenario scenario) {
    counter += 1;
}

Question:

I have a Scenario in the feature file, whose Then steps list the number of fields from JSON which should be confirmed that they are present in Response body. Step in the Scenario of feature file is: Then The response fields should be modificationDate, startDate, endDate, id

translated into this following step method

@Then("The response fields should be {string}, {string}, {string}, {string}")
public void the_response_fields_should_be(String strModification, 
String strStartdate, String strEndDate, String strId)

Instead of having multiple parameters, how can I have a List of Strings like:

public void the_response_fields_should_be(List <String> parameter)

Answer:

Use DataTable

Gherkin:

Then The response fields should be 
   | modificationDate | startDate | endDate | id |

Step definition:

@And("^Then The response fields should be$")
public void thenTheResponseFieldsShouldBe(DataTable table)
{
    List<List<String>> data = table.asLists(String.class);
    String modificationDate = data.get(0).get(0);
    String startDate = data.get(0).get(1);
    String endDate = data.get(0).get(2);
    String id = data.get(0).get(3);
}

Question:

I have a need to run a bunch of Java cucumber feature files, one by one, by using a bash script on MacOS High Sierra. The problem I have is, as soon as the first feature file is done executing (either success or failure), the Cucumber framework does its reporting on that feature file and my script does not execute the remaining feature files. It "returns" to the command line.

Here is part of the script that runs the cucumber files one by one:

function run_cucumber_features {
  for file in $(find ./src/test  -name '*Steps.feature' -print0 | xargs -0);
    do gradle cucumberTest -Dcucumber.options="$file" DmutationTesting="false" -DmutationParameter="$parameter";
  done
}

For example, let's say I execute my script:

./mutation_testing.sh 

The script then invokes Cucumber and the first feature the script finds execute, and then it 'exits' with the status code for that specific feature:

BUILD Success in 18s
7 actionable tasks: 5 executed, 5 succeeded

However, it then does not proceed to execute the next feature file, it returns to the command line:

username$ 

My question is whether there is a way for my script to not stop executing once Cucumber has done its reporting after every feature file that has been executed?


Answer:

The error seems to be related to the steps inside your build.gradle file or the way you call the function in the Bash script.

A small test set-up. Assume the following structure#!/bin/bash

run-gradle-loop.sh                    # executable script
gradle                                # executable script, as simple replacement
src/test/subdir/file2_Steps.feature   # a dummy file
src/test/file1_Steps.feature          # a dummy file

run-gradle-loop.sh

#!/bin/bash

function run_cucumber_features {
  for file in $(find ./src/test  -name '*Steps.feature' -print0 | xargs -0);
  do
    gradle cucumberTest -Dcucumber.options="$file" DmutationTesting="false" -DmutationParameter="$parameter";
    echo "return code = $?"
  done
}

# to run the gradle script in the current directory
export PATH=$(pwd):${PATH}

run_cucumber_features

gradle

#!/bin/bash

echo
echo "running gradle dummy"
echo "passed parameters : $@"

# exit with an error code
exit 1

file1_Steps.feature and file2_Steps.feature are two empty files, only to fulfill the loop criteria.

The aim of the test is to check the behavior where gradle exit with an error code.

run the main Bash script

./run-gradle-loop.sh

output

running gradle dummy
passed parameters : cucumberTest -Dcucumber.options=./src/test/subdir/file2_Steps.feature DmutationTesting=false -DmutationParameter=
return code = 1

running gradle dummy
passed parameters : cucumberTest -Dcucumber.options=./src/test/file1_Steps.feature DmutationTesting=false -DmutationParameter=
return code = 1

This shows that even gradle would return with an error code the loop processes all .*Steps.feature files.

edit One way it might stop after the first error could be that in the run-gradle-loop.sh script there is a set -e statement.

man bash

-e Exit immediately if a pipeline (which may consist of a single simple command), a list, or a compound command

Which means. When the script gradle fails with an error the control is not returned to run-gradle-loop.sh. The output with above set-up would be

$ ./run-gradle-loop.sh

running gradle dummy
passed parameters : cucumberTest -Dcucumber.options=./src/test/subdir/file2_Steps.feature DmutationTesting=false -DmutationParameter=

Question:

I have a large number of feature files right now and I am trying to categorize the features with folders inside resources. When I do this I get this error:

Exception in thread "main" java.lang.IllegalArgumentException: Not a file or directory:

It then proceeds to display the directory going to the resources package.

I have tried changing the path through the cucumber options in the runner, however I am running the features files as cucumber features and It appears to just disregard all the options from the runner.


Answer:

So for some reason, the IDE wouldn't actually refactor the location of the feature files when I moved them, however I was able to fix this problem by creating new feature files in the desired folder and just copy/paste the content over. Problem solved.

Question:

Problem: I need to run my cucumber .feature file to execute in an order defined by me and rather not to run in the default order which is the folder structure.

I am running Appium for Android Native Apps built using cucumber .features file. on windows machine, running on actual devices.

Now my Runcuckes file looks like below:

package runner;

import org.junit.runner.RunWith;
import org.testng.annotations.Test;

 import cucumber.api.CucumberOptions;
 import cucumber.api.junit.Cucumber;
 import cucumber.api.testng.AbstractTestNGCucumberTests;

 //@RunWith(Cucumber.class)

 @CucumberOptions(features = { "src/test/java/features" }, 
             glue = { "Steps" }, 
             monochrome = true, 
             tags = {  "@CustomerInsightsSurveyPopupGiveFeedback,"
                     + "@TestAccountSceanrios"
                     + "@ShortlistPage,"
                     + "@SavedSearchesPage,"
                     + "@SearchResultPage,"
                     + "@Short,"
                     + "@SuggestedSearch" })

        // public class RunCucke {
         public class RunCucke extends AbstractTestNGCucumberTests {
           }

Answer:

Running your features or scenarios in order is Cuking the WRONG way.

In all testing linking one test to another is an anti-pattern. It makes your tests fragile and difficult to debug. Each test should be independent of every other test.

In Cucumber you use Givens to setup the state of your scenario. When's to actually do something. Then's to check your results. Your scenarios Given's should include everything needed to setup your application so you can do your When.

Cucumber encourages you to run your scenarios in a random order, and to reset just about everything between each scenario. Don't work against this, you will make things much more difficult if you do.