Hot questions for Using Cucumber in automated tests

Top Java Programmings / Cucumber / automated tests

Question:

The piece of code I have below compares two list. In my step I use an if statement to check if the destinationList is empty, if so the test is correct and the cucumber steps should proceed.

However if the else statement is reached is there a way I can cause the cucumber test to fail? `

if (destinationList.isEmpty()) {
    System.out.println("This report is correct");

} else {
     System.out.println("This report is incorrect.");
     System.out.println("This list conatains the expected values of the report and their locations:");
     System.out.println("expected = "+sourceList);
     System.out.println("This list contains the actual value from this report and their locations:");
     System.out.println("actual = "+destinationList);
}

Answer:

Do you use JUnit as your test framework? If so then use

fail("Reason of fail")

This is a static method from class Assert http://junit.sourceforge.net/javadoc/org/junit/Assert.html

Question:

What I am trying to do:

Generate a test report after the test execution is done and then email it( I am using Maven, cucumber and RestAssured).

The issue that I am facing:

Everything from the above mentioned is happening, except the test report which gets e-mailed is actually from previous test execution. That is, the report or the folder that has the report, is not getting refreshed when the code to email the report runs.

Is there any way to refresh the folder at the end of the test execution through maven or is there any other way with which I can send the latest test report..?

Any pointer is much appreciated. Below is my Cucumber runner code,

@RunWith(Cucumber.class)
@CucumberOptions(
    features = "src/test/resources/Feature"
    ,glue= "com/sss/tests/RestApi"
    ,tags = {"@TestInDevelopment"}
    ,plugin = {"com.cucumber.listener.ExtentCucumberFormatter:/Report.html"}        
    ,format = {"pretty","html:target/cucumber"}
    ,monochrome = true
    )

public class TestRunner { 
static Configurations config = new Configurations();

@BeforeClass
public static void setup(){

    /*
     * Loading the log4j configurations, before the start of test execution
     */     
    String folderName = "PropertyFiles";
    String fileName = "log4j.properties";
    PropertyConfigurator.configure(config.getResourcePath(folderName)+fileName);

}

@AfterClass
public static void teardown() throws UnknownHostException, IOException, InterruptedException {

    /*
     * Loading the configuration file for the test execution report and setting up the user name, OS info and host details in the report
     */     
    Reporter.loadXMLConfig(new File(config.getResourcePath("Resources")+"extent-config.xml"));
    Reporter.setSystemInfo("USER", System.getProperty("user.name"));
    Reporter.setSystemInfo("OS", System.getProperty("os.name"));
    Reporter.setSystemInfo("HOST NAME", InetAddress.getLocalHost().getHostName());  

   /*
    * After the test execution is completed, parsing the generated test execution report to to see if there is any failures and based on that,
    * sending the Build Success/Failure e-mail to the configured mail list
    */        
    HTML_TestExecutionReportParser testExecutionStatusParser = new HTML_TestExecutionReportParser();    
    TestExecutionReportEmailSender testExecutionReportMailSender = new TestExecutionReportEmailSender();        
    testExecutionReportMailSender.sendTestExecutionReportEmail(testExecutionStatusParser.isAssertionFailureFound(), testExecutionStatusParser.errorsFoundList());     

}

}


Answer:

You can try with placing the emailing code inside a JVM shutdown hook. Thus it will be called when every other process is done.

Example of a shutdown hook -- https://www.geeksforgeeks.org/jvm-shutdown-hook-java/

Question:

What's the best way to fill in a web form with lots of text inputs if the project is using Cucumber and the Page Object Model?

For example, let's say the feature file is something like this:

Scenario: As someone who wants to sign up
    When I visit the homepage
    And I click on the Register button
    And I enter my firstname
    And I enter my surname
    And I enter my email address
    And I enter a new password
    And I re-enter my new password
    And I agree to the terms and conditions
    And I click the Submit button
    Then I should see a welcome page

I understand that the step defs generated by Cucumber would generate a separate method for each of these, which is fine. Would I then have to implement each of these steps in the "RegistrationPage" in its own method? What I'm trying to get at is: is there a way to implement a kind of "fillInform()" method instead of separate methods in the RegistrationPage?

EDIT:

The question I asked is probably wrong (I was trying to keep it short). My objective is to be able to do something like this:

Scenario Outline: As someone who wants to sign up
    When I visit the homepage
    And I click on the Register button

    And I enter my "<firstname>" in the firstname input
    And I enter my "<surname>" in the surname input
    And I enter my "<emailaddress>" in the email input
    And I enter my "<password>" in the password input
    And I enter my "<password>" in the password confirmation input
    And I agree to the terms and conditions
    And I click the Submit button
    Then I expect the registration to "<ExpectedResult>"

    Examples:
    | firstname | surname    | emailaddress          | password       | ExpectedResult |
    | First     | User       | first@somewhere.com   |                | Fail           |
    | Second    | User       | second@somewhere.com  | .              | Fail           |
    | Third     | User       | third@somewhere.com   | toofew         | Fail           |
    | Fourth    | User       | fourth@somewhere.com  | weakpassword   | Fail           |
    | Fifth     | User       | fifth@somewhere.com   | MissingNumber  | Fail           |
    | Sixth     | User       | sixth@somewhere.com   | m1ssingc4pital | Fail           |
    | seventh   | User       | seventh@somewhere.com | CapsAndNumb3r  | Pass           |

Given such a scenario outline, would it still be possible to fill in the registration form using a single method? Something I have thought of (and I'm not sure what the implications of this would be) is to:

@When("^I enter \"([^\"]*)\" in the firstname input$")
public void enterFirstname(String firstname) {
    registrationPage.firstname = firstname;
}

and then, when the test presses the "Submit" button:

@When("^I click the Submit button$")
public void clickSubmitButton() {
    registrationPage.fillInForm();
    registrationPage.clickJoinButton();
}

However, doing it this way just doesn't "feel right" to me (although I could be mistaken - perhaps it's acceptable?)


Answer:

You can use a combination of datatable and scenario outline to accomplish this.

..
..
And Enter form details
    | firstname | surname |.........| password | reppwd |
    | <fname>   | <sname> |.........| <pwd>    | <rpwd> |
..
..

Examples:
| fname  | sname  |.........| pwd  | rpwd |
| Name1  | Title1 |.........| pwd1 | pwd1 |
| Name2  | Title2 |.........| pwd2 | pwd2 |
| Name3  | Title3 |.........| pwd3 | pwd3 |

You can use the raw datatable to get the data in the step definition.

public void enterDetails(DataTable tab) { }

Or create a dataobject(UserDetails) using the headers of datatable (firstname, surname...) as instance variables.

public void enterDetails(List<UserDetails> tab) { }

Question:

trying to run all my Cucumber tests with TestNG. However my suite is not being found.

I saw some stackoverflow questions about it but none of them solved my problem.

Runner - junitRunner.java

package testRunner;

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

//@RunWith(Cucumber.class)
@CucumberOptions(
features = "src/test/resources/features/",
glue = "br.mysteps.steps"
)

public class junitRunner {

}

testng.xml

<suite name="SeleniumSuite">
<test name="testAll">
       <classes>
          <class name="testRunner.junitRunner"/>
       </classes>
</test>
</suite>

pom.xml

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

    <dependency>
        <groupId>org.testng</groupId>       
        <artifactId>testng</artifactId>
        <version>6.11</version>
    </dependency>
</dependencies>

When I run the testng.xml file as TestNG, the tests are not found as below

[RemoteTestNG] detected TestNG version 6.11.0
[TestNGContentHandler] [WARN] It is strongly recommended to add "<!DOCTYPE 
suite SYSTEM "http://testng.org/testng-1.0.dtd" >" at the top of your 
file, otherwise TestNG may fail or not work as expected.

===============================================
SeleniumSuite
Total tests run: 0, Failures: 0, Skips: 0
===============================================

Answer:

If you would like to basically use TestNG to run your cucumber tests, then you would need to extend cucumber.api.testng.AbstractTestNGCucumberTests.

For more detailed samples on how to use TestNG to run your cucumber tests, please refer to the examples here.

Question:

How can I pass java objects?

Scenario: Java Object test
    When I POST the URL to "/v1/gitlab/project/demo" with <java_object>
    Then I expect to see the response code "200"
    And I expect to see "json" content

How can I pass a java object to cucumber in this manner? Or if not java object, then can i pass a json file?


Answer:

A lot easier to read would be to use a datatable for this:

Given I have the following data:
 | property1 | property2 |
 | abc       | 123       |

With the following step definition:

@Given("^I have the following data:$")
public void given_data(DataTable table) {
    final List<Map<String, String>> rows = table.asMaps(String.class, String.class);
    final Map<String, String> data = rows.get(0);
    final String property1 = data.get("property1");
}

I would also suggest only specifying the properties that are relevant for the business case, and add any technical properties inside the step definition. Talking about POST and specific URLs is also already to technical for a cucumber scenario, at least in my opinion.

Question:

I am running my Cucumber suite tests with TestNG (Selenium + Java) and getting java.lang.NullPointerException.

I realized the problem is that my @BeforeTest() is being ignored for some reason causing the NullPointer problem.

I am using the TestNG 7.0.0 (but tried to use latest Beta also).

@BeforeTest() 
public void setUp() {
    driver = Web.createChrome(); // it call a method that has the Chromedriver
}

Web.java

public class Web {

public static WebDriver createChrome() {

    System.setProperty("webdriver.chrome.driver", webdriver_path);

    WebDriver driver = new ChromeDriver();
    driver.manage().window().maximize();
    driver.manage().timeouts().pageLoadTimeout(30, TimeUnit.SECONDS);
    driver.manage().timeouts().implicitlyWait(30, TimeUnit.SECONDS);
    driver.get("http://the-internet.herokuapp.com/");

    return driver;
}
}

Output

java.lang.NullPointerException
at br.dsanders.steps.steps.accessing_the_Tnternet_herokuapp_com_website(steps.java:62)
at ?.Given accessing the Tnternet.herokuapp.com website(testing.feature:9)

Answer:

Try like below:

public class steps {


    WebDriver driver = null;

    public steps() {

        this.driver=Web.createChrome();

    }

@BeforeMethod() 
public void setUp() {
    driver.get("http://the-internet.herokuapp.com/");
  }
}

Note ClassName here is steps if you have other class name then change the class name and constructor name.

Change the @BeforeTest to @BeforeMethod

Source:

What is the difference between BeforeTest and BeforeMethod in TestNG

Question:

I need to list a specific directory using wildcard logic within my Maven goals and options command.

Currently the root directory is: mvn test -Dcucumber.options="C:/Users/Joe_Blogs/Desktop/AutoFramework/src/test/resources/features/Bookings/MakeBooking.feature"

I need to use ** to scan the project folders in order to search for a given feature file, as the folder name (Bookings) may change. mvn test -Dcucumber.options="C:/Users/Joe_Blogs/Desktop/AutoFramework/src/test/resources/features/**/MakeBooking.feature"

In the example above ** will need to reference a variety of different folders, not just Bookings.

Any ideas?

Thanks for your help.


Answer:

Maven supports the "any" and "any descendant" wildcard denoted by * and **, respectively. It is a subset of the <fileset> Ant convention.

The support comes from the Apache Maven Shared Utils library. The actual logic of walking directory trees, path normalization, pattern matching, etc. is grouped inside the org.apache.maven.shared.utils.io package. Those classes provides uniform file system handling across plugins supported by the the Maven Project.

As the references should demonstrate, wildcard processing is neither trivial logic, nor magically applied outside of Maven proper. Cucumber has to intentionally support the syntax somehow. Sorry, but it doesn't look like Cucumber supports the "any descendant" wildcard. The closest equivalent is /* at the end of a path.

However, one possible workaround is to use tags. Maybe it will seem silly to tag a single file, but doing so dispenses any concern about pathing. Example:

mvn test -Dcucumber.options="--tags @MakeBooking"

Question:

We have application which use Cucumber framework for testing our second application, the applications runs on own processes (black box testing), currently we do following steps:

1) Run DB

2) Run main application

3) Run test application which use Cukumber framework for testing main application

Question is: how we can do this automatically by using TeamCity ?


Answer:

  1. Create a Command Line build step:

  1. Point to the working directory
  2. Run your Cucumber tests from the command line. Example.

Here is more info on Cucumber's CLI.