Implicit and Explicit Wait in Selenium WebDriver

HOME

 driver.manage().timeouts().implicitlyWait(Duration.ofSeconds(2));

import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.chrome.ChromeDriver;
import java.time.Duration;

public class implicitDemo {

    public static void main(String args[]) {

        WebDriver driver = new ChromeDriver();
        driver.manage().window().maximize();
        driver.manage().timeouts().implicitlyWait(Duration.ofSeconds(5));
        driver.get("https://www.selenium.dev/selenium/web/dynamic.html");
        driver.findElement(By.id("adder")).click();
        WebElement added = driver.findElement(By.id("box0"));
        System.out.println("Color :" + added.getDomAttribute("class"));
        driver.quit();
    }

}

driver.manage().timeouts().implicitlyWait(TimeOut, TimeUnit.SECONDS);

Implicit wait will accept 2 parameters, the first parameter will accept the time as an integer value and the second parameter will accept the time measurement in terms of SECONDS, MINUTES, MILISECOND, MICROSECONDS, NANOSECONDS, DAYS, HOURS, etc.

Let me show how to use implicit wait in our program

import java.util.concurrent.TimeUnit;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.firefox.FirefoxDriver;
 
public class ImplicitWait_Example {
      public static void main(String[] args) {
                      
     System.setProperty("webdriver.gecko.driver","C:\\Users\\vibha\\Downloads\\geckodriver.exe");
      WebDriver driver = new FirefoxDriver();
                    
      //Implicit Wait
      driver.manage().timeouts().implicitlyWait(30, TimeUnit.SECONDS);
      driver.get("https://www.facebook.com");
      driver.findElement(By.name("email")).sendKeys("vibhasingh.verma");
          }
}

In the above example, we have waited for 30 sec, before redirecting the web page to the URL explicitly mentioned in the code.


Explicit Wait


An explicit wait is code you define to wait for a certain condition to occur before proceeding further in the code. The worst case of this is Thread.sleep(), which sets the condition to an exact time period to wait. There are convenience methods available to help write code that will only wait as long as required. 

WebDriverWait in combination with ExpectedCondition is one way to do this.

The explicit wait will tell the web driver to wait for certain conditions like visibilityOfElementLocated and maximum amount of time before throwing NoSuchElementException exception.

Wait<WebDriver> wait = new WebDriverWait(driver, Duration.ofSeconds(2));
 wait.until(d -> revealed.isDisplayed());

package org.example;

import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.support.ui.Wait;
import org.openqa.selenium.support.ui.WebDriverWait;

import java.time.Duration;

public class explicitDemo {

    public static void main(String args[])  {

        WebDriver driver = new ChromeDriver();
        driver.manage().window().maximize();
        driver.manage().timeouts().implicitlyWait(Duration.ofSeconds(5));
        driver.get("https://www.selenium.dev/selenium/web/dynamic.html");
        driver.findElement(By.id("reveal")).click();

        WebElement revealTextBox = driver.findElement(By.id("revealed"));
        Wait<WebDriver> wait = new WebDriverWait(driver, Duration.ofSeconds(3));
        wait.until(d -> revealTextBox.isDisplayed());

        revealTextBox.sendKeys("Happy");
        System.out.println("Input Text :" + revealTextBox.getDomProperty("value"));

        driver.quit();
    }
}

WebDriverWait wait = new WebDriverWait(WebDriverRefrence,TimeOut);
wait.until(ExpectedConditions.visibilityOfElementLocated(By.id("Stats1_totalCount")));

Let me explain this with an example

import java.util.concurrent.TimeUnit;
 
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.support.ui.ExpectedConditions;
import org.openqa.selenium.support.ui.WebDriverWait;
 
public class ExplicitWaitExample {

            public static void main(String[] args) {
                        System.setProperty("webdriver.chrome.driver",
                                           "C:\\Users\\Vibha\\Desktop\\SeleniumKT\\chromedriver.exe");
                        // Create a new instance of the Firefox driver
                        WebDriver driver = new ChromeDriver();
                        driver.manage().window().maximize();
                        driver.manage().timeouts().implicitlyWait(30, TimeUnit.SECONDS);
                        driver.get("https://configureselenium.blogspot.com/");
 
                        // Click on READ MORE link. New Page is opened
                        driver.findElement(By.linkText("READ MORE")).click();
 
                        // Explicit Wait
                        WebDriverWait wait = new WebDriverWait(driver, 60);
                    wait.until(ExpectedConditions.visibilityOfElementLocated(By.id("Stats1_totalCount")));
                        String Count = driver.findElement(By.id("Stats1_totalCount")).getText();
                        System.out.println("Count is :" + Count);
                  driver.close();
            }
}

In the above example, we have used Explicit Wait. We are waiting for the web element – Stats1_totalCount for 60 seconds before performing the next operation.

The following are the Expected Conditions that can used in Explicit Wait

  1. alertIsPresent()
  2. elementSelectionStateToBe()
  3. elementToBeClickable()
  4. elementToBeSelected()
  5. frameToBeAvaliableAndSwitchToIt()
  6. invisibilityOfTheElementLocated()
  7. invisibilityOfElementWithText()
  8. presenceOfAllElementsLocatedBy()
  9. presenceOfElementLocated()
  10. textToBePresentInElement()
  11. textToBePresentInElementLocated()
  12. textToBePresentInElementValue()
  13. titleIs()
  14. titleContains()
  15. visibilityOf()
  16. visibilityOfAllElements()
  17. visibilityOfAllElementsLocatedBy()
  18. visibilityOfElementLocated()

Note:-  Do not mix implicit and explicit waits! Doing so can cause unpredictable wait times. For example, setting an implicit wait of 20 seconds and an explicit wait of 35 seconds could cause a timeout to occur after 25 seconds.

Fluent Wait

The Fluent wait will tell the web driver to wait for certain conditions like visibilityOfElementLocated as well as the frequency with which we want to check before throwing NoSuchElementException exception.

To know more about Fluent Wait, please click here

DataProviders in TestNG

HOME

In the last tutorial, I have explain the Parameters in TestNG which passes different test data to the test case as arguments. Similar to TestNG Parameters, DataProviders are a means to pass data to test scripts in TestNG. In this tutorial, I will explain about the DataProviders in TestNG.

What is DataProvider in TestNG?

The DataProvider in TestNG is another way to pass the parameters in the test function, the other one being TestNG parameters. Using DataProvider in TestNG, we can easily inject multiple values into the same test case. It comes inbuilt in TestNG and is popularly used in data-driven frameworks.

Syntax of DataProvider

@DataProvider (name = "name_of_dataprovider")
public Object[][] dpMethod() {
    return new Object [][] { values}
}
  •  A Data Provider is a method on the class that returns an array of array of objects.  This method is annotated with @DataProvider
  • A @Test method specifies its Data Provider with the dataProvider attribute. This name must correspond to a method on the same class annotated with @DataProvider(name=”…”) with a matching name.
  • TestNG dataprovider returns a 2d list of objects..An array of array of objects (Object[][]) where the first dimension’s size is the number of times the test method will be invoked and the second dimension size contains an array of objects that must be compatible with the parameter types of the test method.
  • DataProviders are not declared on top of the functions like TestNG parameters but have a method of their own, which in regular speaking terms called a dataprovider method. For example, dpMethod here.
  • The dataprovider name calls the dataprovider method, and if there is no name specified by the tester, then the dataprovider method is the default name used in the receiving @Test case.
  • Data providers can run in parallel with the attribute parallel.

Below is the basic example of using DataProvider in TestNG.

import org.openqa.selenium.By;
import org.openqa.selenium.Keys;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.chrome.ChromeOptions;
import org.testng.annotations.AfterMethod;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;

public class DataProvider_Demo {

    WebDriver driver;

    @DataProvider(name = "testData")
    public Object[][] dataProvFunc() {
        return new Object[][] { { "Selenium" }, { "TestNG" } };
    }

    @BeforeMethod
    public void setUp() {

        System.out.println("Start the test");
        ChromeOptions options = new ChromeOptions();
        options.addArguments("--start-maximized");
        driver = new ChromeDriver(options);
        driver.get("https://www.bing.com/");
        
    }

    // Passing the dataProvider to the test method through @Test annotation
    @Test(dataProvider = "testData")
    public void search(String keyWord) {
        WebElement txtBox = driver.findElement(By.id("sb_form_q"));
        txtBox.sendKeys(keyWord);
        System.out.println("Keyword entered is : " + keyWord);
        txtBox.sendKeys(Keys.ENTER);
        System.out.println("Search result is displayed.");
    }

    @AfterMethod
    public void burnDown() {
        driver.quit();

        System.out.println("End the test");
    }

}

In the above example, I am passing two search keywords, viz “Selenium” and “TestNG” to the test method using the DataProvider method. You can run the code and check the output.

Here, Test is executed with two values, but we have run the test only once.

Inheriting DataProvider in TestNG

It is messy to have supporting methods like DataProvider and test code in one class. It is always preferred to declare the test case in one class and define TestNG parameters like DataProviders in another class. By default, the data provider will be looked for in the current test class or one of its base classes. If you want to put your data provider in a different class, it needs to be a static method or a class with a non-arg constructor, and you specify the class where it can be found in the dataProviderClass attribute.

Let us create separate classes for the DataProvider method and the test method, as shown below:

DataProvider Class

public class DPDemo {

	@DataProvider(name = "testData")
	public Object[][] dataProvFunc() {
		return new Object[][] { 
          { "Selenium" }, { "TestNG" }, { "Automation" } };
	}
}

We can see that all we did was create a DataProvider method in a Class and create a new class for Test Code.

import org.openqa.selenium.By;
import org.openqa.selenium.Keys;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.chrome.ChromeOptions;
import org.testng.annotations.AfterMethod;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test;

public class DataProviderInheritance_Demo {

    WebDriver driver;

    @BeforeMethod
    public void setUp() {

        System.out.println("Start the test");
        ChromeOptions options = new ChromeOptions();
        options.addArguments("--start-maximized");
        driver = new ChromeDriver(options);
        driver.get("https://www.bing.com/");

    }

    // Passing the dataProvider to the test method through @Test annotation
    @Test(dataProvider = "testData", dataProviderClass = DPDemo.class)
    public void search(String keyWord) {
        WebElement txtBox = driver.findElement(By.id("sb_form_q"));
        txtBox.sendKeys(keyWord);
        System.out.println("Keyword entered is : " + keyWord);
        txtBox.sendKeys(Keys.ENTER);
        System.out.println("Search result is displayed.");
    }

    @AfterMethod
    public void burnDown() {
        driver.quit();
        System.out.println("End the test");
    }

}

As you can see, to handle the inheritance, all we did was add an attribute to the test method (highlighted above), which specifies the class that has the DataProvider method. 

Passing Multiple Parameter Values in TestNG DataProviders

Passing multiple values is pretty similar to passing numerous parameters. The only difference is that we will pass various values to a single parameter so that a string of input(s) is sent in one go.

Let us quickly understand this concept with the help of the code as shown below.

DataProvider Class

public class DPDemo {

	@DataProvider(name = "testData")
	public Object[][] dataProvFunc() {
		return new Object[][] { { "Automation Tester", "2-5 years" }, { "Performance Tester", "3+ years" },
				{ "DevOps", "5+ years" } };
	}
}

Test Code – DataProviderInheritanceDemo

import org.openqa.selenium.By;
import org.openqa.selenium.Keys;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.chrome.ChromeOptions;
import org.testng.annotations.AfterMethod;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test;

public class DataProviderInheritanceDemo {

    WebDriver driver;

    @BeforeMethod
    public void setUp() {

        System.out.println("Start the test");
        ChromeOptions options = new ChromeOptions();
        options.addArguments("--start-maximized");
        driver = new ChromeDriver(options);
        driver.get("https://www.bing.com/");

    }

    // Passing the dataProvider to the test method through @Test annotation
    @Test(dataProvider = "testData", dataProviderClass = DPDemo.class)
    public void search(String keyWord1, String keyWord2) {

        WebElement txtBox = driver.findElement(By.id("sb_form_q"));
        txtBox.sendKeys(keyWord1, keyWord2);
        System.out.println("Keyword entered is : " + keyWord1 + " " + keyWord2);
        txtBox.sendKeys(Keys.ENTER);
        System.out.println("Search result is displayed.");
    }

    @AfterMethod
    public void burnDown() {
        driver.quit();
        System.out.println("End the test");
    }
}

Run the test script, and you will see both the values for the TestNG parameters being passed in one go.

We are done! Congratulations on making it through this tutorial and hope you found it useful! Happy Learning!!

Switch Window Commands in Selenium WebDriver

HOME

One of the major testing workflows involves switching between multiple windows. Selenium WebDriver has specific switch commands to serve this purpose. Selenium WebDriver assigns an alphanumeric id to each window as soon as the WebDriver object is instantiated. This unique alphanumeric id is called a window handle. Selenium uses this unique id to switch control among several windows. In simple terms, each unique window has a unique ID, so that Selenium can differentiate when it is switching controls from one window to the other.

1) GetWindowHandle

To get the window handle of the current window. It returns a string of alphanumeric window handles.

String  parentHandle= driver.getWindowHandle();

2) GetWindowHandles

To get the window handle of all the windows. It returns a set of window handle.

Set  handle= driver.getWindowHandles();

3) SwitchTo Window

WebDriver supports moving between named windows using the “switchTo” method.

driver.switchTo().window("windowName");

Let us explain window switch with an example:-

1) Launch new Browser and open https://demoqa.com/browser-windows
2) Check the count of windows which is 1
3) Locate “New Window” button using Id – “windowButton” and click to open a new window
4) Get the count of both windows which is now 2.
5) Get the parent window handle and print it to console
6) Get the window handles of both the open windows and print them
7) Switch to the new window (child window)
8) Get the text of Child Window and print it
9) Close the new window (child window)

The program for the above scenario is shown below:

package com.example.definitions;

import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.chrome.ChromeOptions;
import java.util.Iterator;
import java.util.Set;
import java.util.concurrent.TimeUnit;

public class WindowSwitchDemo {

    public static void main(String[] args) {

        ChromeOptions options = new ChromeOptions();
        options.addArguments("--start-maximized");
        WebDriver driver = new ChromeDriver(options);
        driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS);

        // Pass application url
        driver.get("https://demoqa.com/browser-windows");

        //Count of window - 1
        Set<String> allWindowHandles = driver.getWindowHandles();
        System.out.println("Count of Window :" + allWindowHandles.size());

        //Open a child window
        driver.findElement(By.id("windowButton")).click();

        //Count of windows , changed from 1 to 2
        Set<String> newAllWindowHandles = driver.getWindowHandles();
        System.out.println("New Count of Window :" + newAllWindowHandles.size());

        // Get the detail of the parent window
        String ParentHandle = driver.getWindowHandle();
        System.out.println("Parent Window :" + ParentHandle);

        //Get details of parent and child windows
        Iterator<String> iterator = newAllWindowHandles.iterator();
        String mainWindow = iterator.next();
        String childWindow = iterator.next();
        System.out.println("Parent Window :" + mainWindow);
        System.out.println("Child Window :" + childWindow);

        //Switch control to child window
        driver.switchTo().window(childWindow);

        //Verify the text present on child window
        WebElement text = driver.findElement(By.id("sampleHeading"));
        System.out.println("Child_Title :" + text.getText());

        // Close Child window
        driver.close();

        // Switch back to parent window
        driver.switchTo().window(ParentHandle);
        System.out.println("Parent Title :" + driver.getTitle());

        // Close Parent window
        driver.quit();
    }

}

What is the difference between driver.close() and driver.quit()?

When we are working on multiple windows and a selective window needs to be closed, then transfer the control to that window and use driver.close() to close the selective window. This will not stop the execution of the rest of the program. But, in case it is needed to close all the open windows, then use driver.quit() which will close all the windows opened in a particular session. It basically stops the driver instance, and any further actions to WebDriver may result in an exception.  It is generally the last statement of any code.

Congratulations. We have learnt about window switching in Selenium. I hope you find this tutorial helpful. Happy Learning!!

DataTables in Cucumber

Last Updated On

HOME

Cucumber Data Tables can be used to add multiple parameters in Step Definition in a tabular form rather than putting all the parameters in the Gherkin statement. This is much easier to read and multiple rows of data can be passed in the same step. Data tables from Gherkin can be accessed by using the DataTable object as the last parameter in a Step Definition. This conversion can be done either by Cucumber or manually.

Table Of Contents

  1. Prerequisite
  2. Project Structure
    1. Table into List of a List of Strings
    2. Table into List of Maps
    3. Table into Single Map
    4. Table into map that uses a list as its value
  3. Cucumber Data Tables Example in Java
    1. Data Table without Header Example
    2. Data Table with Header and Single Row Example
    3. Data Table with Header and Multiple Rows Example

Prerequisite

  1. Cucumber – 7.15.0
  2. Java – 17
  3. Selenium – 4.16.1
  4. JUnit – 4.13.2 ( You can use TestNG also)
  5. Cucumber JUnit – 7.15.0 (If using TestNG, then replace this with Cucumber TestNG)

Project Structure

Depending on the table shape, we can use one of the following collections:

List<List<String>> table
List<Map<String, String>> table
Map<String, String> table
Map<String, List<String>> table
Map<String, Map<String, String>> table

Let’s write a simple data table and see how we use it.

1. Table into List of a List of Strings

| firstName | lastName | age |
| Thomas    | Brown | 30 |
| Perry     | Wilson | 26 |
| Ashley    | William | 27 |

java type: List<List<String>>

The natural representation of list of a list of strings is shown below.

[ 
  [ "firstName", "lastName", "age" ],
  [ "Thomas", "Brown", "30" ], 
  [ "Perry", "Wilson", "26" ], 
  [ "Ashley", "William", "27" ] 
]

2. Table into List of Maps

java type: List<Map<String, String>>
The natural representation of list of maps is shown below.

[
  { "firstName": "Thomas", "lastName": "Brown",  "age": "30" }, 
  { "firstName": "Perry",  "lastName": "Wilson", "age": "26" }, 
  { "firstName": "Ashley", "lastName": "William", "age": "27" } 
]

3. Table into Single Map

Table where first colum is key as shown below

| IN  | India          |
| IRE | Ireland        |
java type: Map<String, String>

TO convert the table into a single map

{
  "IN": "India",
  "IRE": "Ireland"
}

4. Table into map that uses a list as its value

 A table with multiple column values per key.
 
 | IN  | India          | 29  |
 | IRE | Ireland        | 8   |

java type: Map<String, List<String>>

{
  "IN":  ["India","29"],
  "IRE": ["Ireland","8"]
}

Now, let us see how we can use DataTable in Cucumber

Cucumber Data Tables Example in Java

Data Table without Header Example

Below is an example of how to implement Data Tables without a Header. For example, we want to test the Login Page of an application. We can either mention all the arguments inside the Gherkin statement or use a table to list all the arguments, as we used below:

Feature: Login to HRM Application 
 
  @ValidCredentials
  Scenario: Login with valid credentials - Data Table without Header

    Given User is on HRMLogin page
    When User enters valid credentials
      | Admin | admin123 |
    Then User should be able to login successfully and new page open

Below is the Step Definition of the above scenario.

import io.cucumber.datatable.DataTable;
import io.cucumber.java.After;
import io.cucumber.java.Before;
import io.cucumber.java.en.Given;
import io.cucumber.java.en.Then;
import io.cucumber.java.en.When;
import org.junit.Assert;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import static org.hamcrest.CoreMatchers.containsString;
import static org.hamcrest.MatcherAssert.assertThat;

public class DataTableDefinitions {

    WebDriver driver;

 @Before
    public void setup() {

        ChromeOptions options = new ChromeOptions();
        options.addArguments("--start-maximized");
        driver = new ChromeDriver(options);
        driver.manage().timeouts().implicitlyWait(Duration.ofSeconds(5));

    }

    @Given("User is on HRMLogin page")
    public void userOnHomePage() {

        driver.get("https://opensource-demo.orangehrmlive.com/");
    }

     @When("User enters valid credentials")
    public void entersValidCredential(DataTable dataTable) throws InterruptedException{

        System.out.println("Credentials Entered");

        List<List<String>> signUpForm = dataTable.asLists(String.class);
        String userName = signUpForm.get(0).get(0);
        String passWord = signUpForm.get(0).get(1);
        driver.findElement(By.name("username")).sendKeys(userName);
        driver.findElement(By.name("password")).sendKeys(passWord);
        driver.findElement(By.xpath("//*[@class='oxd-form']/div[3]/button")).submit();
    }

    @Then("User should be able to login successfully and new page open")
    public void successfulLogin() throws InterruptedException {

        String newPageText = driver.findElement(By.xpath("//*[@class='oxd-topbar-header-breadcrumb']/h6")).getText();
        System.out.println("newPageText :" + newPageText);
        assertThat(newPageText, containsString("Dashboard"));
    }

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


To run the Feature file, we need a Cucumber TestRunner.

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

@RunWith(Cucumber.class)
@CucumberOptions(monochrome = true, plugin = "pretty", features = "src/test/resources/Features/DataTable.feature",
        glue = "definitions", tags="@ValidCredentials")

public class CucumberRunnerTest {
}

The output of the above program is

In the above example, we don’t have a header. We have just got the List object. We get the values of DataTable starting from 0 index.

Cucumber converts the above table into a list of lists. It treats each row as a list of the column values. We use the asLists method — supplying a String.class argument — to convert the DataTable argument to a List<List<String>>This Clasargument informs the asLists method of what data type we expect each element to be.

Data Table with Header and Single Row Example

Below is a cucumber data tables example with the header.

Adding a header to your table makes it easier to read and maintain.

  @InValidCredential
  Scenario: Login with invalid credential - Header with Single Row

    Given User is on HRMLogin page
    Then User enters invalid credentials and Login will be unsuccessful with error message
      | Username  | Password   | ErrorMessage        |
      | Admin1    | admin123!$ | Invalid credentials |

Below is the Step Definition of the above scenario.

package org.example.definitions;

import io.cucumber.datatable.DataTable;
import io.cucumber.java.After;
import io.cucumber.java.Before;
import io.cucumber.java.en.Given;
import io.cucumber.java.en.Then;
import io.cucumber.java.en.When;
import org.junit.Assert;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.chrome.ChromeOptions;

import java.time.Duration;
import java.util.List;
import java.util.Map;

public class DataTableDefinitions {

    WebDriver driver;

    @Before
    public void setup() {

        ChromeOptions options = new ChromeOptions();
        options.addArguments("--start-maximized");
        driver = new ChromeDriver(options);
        driver.manage().timeouts().implicitlyWait(Duration.ofSeconds(5));

    }

    @Given("User is on HRMLogin page")
    public void userOnHomePage() {

        driver.get("https://opensource-demo.orangehrmlive.com/");
    }

    @Then("User enters invalid credentials and Login will be unsuccessful with error message")
    public void entersInvalidCredential(DataTable userTable) throws InterruptedException {

        System.out.println("Enter Credentials");
        List<Map<String, String>> user = userTable.asMaps(String.class, String.class);

        String userName = user.get(0).get("Username");
        System.out.println("Username :" + userName);
        driver.findElement(By.name("username")).sendKeys(userName);

        String passWord = user.get(0).get("Password");
        System.out.println("Password :" + passWord);
        driver.findElement(By.name("password")).sendKeys(passWord);

        driver.findElement(By.xpath("//*[@class='oxd-form']/div[3]/button")).submit();

        String errorMessage = user.get(0).get("ErrorMessage");
        String actualErrorMessage = driver.findElement(By.xpath("//*[@class='orangehrm-login-error']/div[1]/div[1]/p")).getText();
        System.out.println("Actual Error Message :" + actualErrorMessage);
        Assert.assertTrue(actualErrorMessage.equalsIgnoreCase(errorMessage));

    }

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

}

The output of the above program is

In the above example, we have only 1 row with the header, so have used get(0) to retrieve the first row of DataTable. After that, I used get(“HeaderName”) to get the value of the row of DataTable.

Data Table with Header and Multiple Rows Example

Below is a cucumber data table example with multiple rows of data with the header. This is helpful when we want to test multiple combinations of data in a step.

  @Multiple_InValidCredentials
  Scenario: Login with invalid credentials - Data Table with Header and Multiple Rows

    Given User is on HRMLogin page
    Then User enters invalid credentials and Login will be unsuccessful with custom error messages
      | Username    | Password  | ErrorMessage         |
      | Admin1      | admin123! | Invalid credentials  |
      | Admina      | admin123a | Invalid credentials  |
   

Below is the Step Definition of the above scenario

import io.cucumber.datatable.DataTable;
import io.cucumber.java.After;
import io.cucumber.java.Before;
import io.cucumber.java.en.Given;
import io.cucumber.java.en.Then;
import io.cucumber.java.en.When;
import org.junit.Assert;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import static org.hamcrest.CoreMatchers.containsString;
import static org.hamcrest.MatcherAssert.assertThat;

public class DataTableDefinitions {

    WebDriver driver;

     @Before
    public void setup() {

        ChromeOptions options = new ChromeOptions();
        options.addArguments("--start-maximized");
        driver = new ChromeDriver(options);
        driver.manage().timeouts().implicitlyWait(Duration.ofSeconds(5));

    }

    @Given("User is on HRMLogin page")
    public void userOnHomePage() {

        driver.get("https://opensource-demo.orangehrmlive.com/");
    }

     @Then("User enters invalid credentials and Login will be unsuccessful with custom error messages")
    public void entersInvalidCredentials(DataTable userTable) throws InterruptedException {

        System.out.println("Enter Credentials");

        List<Map<String, String>> user = userTable.asMaps(String.class, String.class);
        for (Map<String, String> form : user) {

            String userName = form.get("Username");
            System.out.println("Username :" + userName);
            driver.findElement(By.name("username")).sendKeys(userName);

            String passWord = form.get("Password");
            System.out.println("Password :" + passWord);
            driver.findElement(By.name("password")).sendKeys(passWord);

            driver.findElement(By.xpath("//*[@class='oxd-form']/div[3]/button")).submit();

            String errorMessage = form.get("ErrorMessage");
            String actualErrorMessage = driver.findElement(By.xpath("//*[@class='orangehrm-login-error']/div[1]/div[1]/p")).getText();
            System.out.println("Actual Error Message :" + actualErrorMessage);

            Assert.assertTrue(actualErrorMessage.equalsIgnoreCase(errorMessage));

        }
    }

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

}

The output of the above program is

Cucumber creates a list containing each row, but instead maps the column heading to each column value. Cucumber repeats this process for each subsequent row. We use the asMaps method — supplying two String.class arguments — to convert the DataTable argument to a List<Map<String, String>>.

The first argument denotes the data type of the key (header). The second indicates the data type of each column value. Thus, we supply two String.class arguments because our headers (key) and title and author (values) are all Strings.

Congratulations on making it through this tutorial and hope you found it useful! Happy Learning!! Cheers!!

Integration of Cucumber with Selenium and JUnit4

HOME

As we know, Cucumber is a BDD Tool and Selenium Webdriver is used for the automation of web applications. Imagine we need to build a test framework that can be used by businesses to understand the test scenarios and as well can test the web application. This can be achieved by integrating Cucumber with Selenium.

In this tutorial, I’ll create a BDD Framework for the testing of web applications using Selenium Webdriver.

Table of Contents

Dependency List:

  1. Cucumber – 7.14.0
  2. Java 17
  3. JUnit – 4.13.2
  4. Maven – 3.9.5
  5. Selenium – 4.15.0

Implementation Steps

The above steps are explained in detail.

Step 1- Download and Install Java

Cucumber and Selenium need Java to be installed on the system to run the tests. Click here to know How to install Java.

Step 2 – Download and setup Eclipse IDE on the system

The Eclipse IDE (integrated development environment) provides strong support for Java developers. The Eclipse IDE for Java Developers distribution is designed to support standard Java development. It includes support for the Maven and Gradle build system and support for the Git version control system. Click here to know How to install Eclipse.

Step 3 – Setup Maven

To build a test framework, we need to add a number of dependencies to the project. It is a very tedious and cumbersome process to add each dependency manually. So, to overcome this problem, we use a build management tool. Maven is a build management tool that is used to define project structure, dependencies, build, and test management. Click here to know How to install Maven.

Step 4 – Install Cucumber Eclipse Plugin (Only for Eclipse)

The cucumber plugin is an Eclipse plugin that allows eclipse to understand the Gherkin syntax. When we are working with cucumber we will write the feature files that contain Feature, Scenario, Given, When, Then, And, But, Tags, Scenario Outline, and Examples. By default, eclipse doesn’t understand these keywords so it doesn’t show any syntax highlighter. Cucumber Eclipse Plugin highlights the keywords present in Feature File. Refer to this tutorial to get more detail – How to setup Cucumber with Eclipse.

Step 5 – Create a new Maven Project

Click here to know How to create a Maven project

Below is the Maven project structure. Here,

Group Id – org.example
Artifact Id – Cucumber_JUnit4_Demo
Version – 0.0.1-SNAPSHOT
Package – cucumber

Maven Dependency (pom.xml) looks like something shown below for a new Maven project.

Step 6 – Create source folder src/test/resources

When a new Maven Project is created, it has 2 folders – src/main/java and src/test/java. To create test scenarios, we need a new source folder called – src/test/resources. To create this folder, Right-click on your Maven project ->select New ->Java, and then Source Folder. The Feature file is created in the src/test/resources source folder.

Mention the source folder name as src/test/resources and click the Next button. This will create a source folder under your new Maven project, as shown in the below image.

Step 7 – Add Selenium and Cucumber dependencies to the project

Add the below-mentioned Selenium and Cucumber dependencies to the project.

<properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <cucumber.version>7.14.0</cucumber.version>
    <selenium.version>4.15.0</selenium.version>
    <junit.version>4.13.2</junit.version>
    <maven.compiler.plugin.version>3.11.0</maven.compiler.plugin.version>
    <maven.surefire.plugin.version>3.2.1</maven.surefire.plugin.version>
    <maven.compiler.source.version>17</maven.compiler.source.version>
    <maven.compiler.target.version>17</maven.compiler.target.version>
  </properties>

  <dependencies>

    <dependency>
      <groupId>io.cucumber</groupId>
      <artifactId>cucumber-java</artifactId>
      <version>${cucumber.version}</version>
    </dependency>

    <dependency>
      <groupId>io.cucumber</groupId>
      <artifactId>cucumber-junit</artifactId>
      <version>${cucumber.version}</version>
      <scope>test</scope>
    </dependency>

    <!-- Selenium -->
    <dependency>
      <groupId>org.seleniumhq.selenium</groupId>
      <artifactId>selenium-java</artifactId>
      <version>${selenium.version}</version>
    </dependency>

    <!-- JUnit4 -->
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>${junit.version}</version>
      <scope>test</scope>
    </dependency>
  </dependencies>

Step 8 – Add Maven Compiler Plugin

The compiler plugin is used to compile the source code of a Maven project. This plugin has two goals, which are already bound to specific phases of the default lifecycle:

  • compile – compile main source files
  • testCompile – compile test source files
<build>
    <plugins>
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-compiler-plugin</artifactId>
        <version>${maven.compiler.plugin.version}</version>
        <configuration>
          <source>${maven.compiler.source.version}</source>
          <target>${maven.compiler.target.version}</target>
        </configuration>
      </plugin>
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-surefire-plugin</artifactId>
        <version>${maven.surefire.plugin.version}</version>
      </plugin>
    </plugins>
  </build>
</project>

The complete pom.xml will look like the below image

<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>org.example</groupId>
  <artifactId>Cucumber_JUnit4_Demo</artifactId>
  <version>1.0-SNAPSHOT</version>
  <packaging>jar</packaging>

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

  <properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <cucumber.version>7.14.0</cucumber.version>
    <selenium.version>4.15.0</selenium.version>
    <junit.version>4.13.2</junit.version>
    <maven.compiler.plugin.version>3.11.0</maven.compiler.plugin.version>
    <maven.surefire.plugin.version>3.2.1</maven.surefire.plugin.version>
    <maven.compiler.source.version>17</maven.compiler.source.version>
    <maven.compiler.target.version>17</maven.compiler.target.version>
  </properties>

  <dependencies>

    <dependency>
      <groupId>io.cucumber</groupId>
      <artifactId>cucumber-java</artifactId>
      <version>${cucumber.version}</version>
    </dependency>

    <dependency>
      <groupId>io.cucumber</groupId>
      <artifactId>cucumber-junit</artifactId>
      <version>${cucumber.version}</version>
      <scope>test</scope>
    </dependency>

    <!-- Selenium -->
    <dependency>
      <groupId>org.seleniumhq.selenium</groupId>
      <artifactId>selenium-java</artifactId>
      <version>${selenium.version}</version>
    </dependency>

    <!-- JUnit4 -->
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>${junit.version}</version>
      <scope>test</scope>
    </dependency>
  </dependencies>

  <build>
    <plugins>
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-compiler-plugin</artifactId>
        <version>${maven.compiler.plugin.version}</version>
        <configuration>
          <source>${maven.compiler.source.version}</source>
          <target>${maven.compiler.target.version}</target>
        </configuration>
      </plugin>
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-surefire-plugin</artifactId>
        <version>${maven.surefire.plugin.version}</version>
      </plugin>
    </plugins>
  </build>
</project>

Step 9 – Create a feature file (LoginPage.feature)

Feature file should be saved as an extension of .feature. Add the test scenarios in this feature file. I have added sample test scenarios. In this feature file, I have created a scenario for successful login and another one for a failed login. The test scenarios are written in the Gherkins language. A feature file contains all the test scenarios and is placed in src/test/resources/features.

Feature: Login to HRM Application 

   @ValidCredentials
   Scenario: Login with valid credentials
    
    Given User is on Home page
    When User enters username as "Admin"
    And User enters password as "admin123"
    Then User should be able to login sucessfully
    
   @InValidCredentials
   Scenario: Login with invalid credentials
    
    Given User is on Home page
    When User enters username as "username"
    And User enters password as "password"
    Then Login will be unsuccessfull with error message "Invalid credentials"

Step 10 – Create the step definition class

The StepDefinition class is created in src/test/java. The StepDefinition class contains the test code corresponding to the steps of Test Scenario in the Feature File.

It is recommended to create a package with a name such as org.example.cucumber.stepdefinitions in src/test/java and create the step definition java file corresponding to the feature files in that package

package org.example.definitions;

import java.time.Duration;

import org.junit.Assert;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.chrome.ChromeOptions;

import io.cucumber.java.After;
import io.cucumber.java.Before;
import io.cucumber.java.en.Given;
import io.cucumber.java.en.Then;
import io.cucumber.java.en.When;

public class LoginStepdefinitions {

	WebDriver driver;
	
	@Before
    public void setUp() {

        ChromeOptions options = new ChromeOptions();
        options.addArguments("--start-maximized");
        driver = new ChromeDriver(options);
        driver.manage().timeouts().implicitlyWait(Duration.ofSeconds(5));

    }
	 
    @Given("User is on Home page")
    public void userOnHomePage() {
    	
        driver.get("https://opensource-demo.orangehrmlive.com/");
    }
 
    @When("User enters username as {string}")
    public void entersUsername(String userName)  {
 
        System.out.println("Username Entered");
        driver.findElement(By.name("username")).sendKeys(userName);
       
 
    }
 
    @When("User enters password as {string}")
    public void entersPassword(String passWord)  {
 
        System.out.println("Password Entered");
        driver.findElement(By.name("password")).sendKeys(passWord);
        driver.findElement(By.xpath("//*[@class='oxd-form']/div[3]/button")).submit();
    }
 
    @Then("User should be able to login sucessfully")
    public void sucessfullLogin()  {
 
    	 String homePageHeading = driver.findElement(By.xpath("//*[@class='oxd-topbar-header-breadcrumb']/h6")).getText();

         //Verify new page - HomePage
         Assert.assertEquals("Dashboard",homePageHeading);   
 
    }
 
    @Then("Login will be unsuccessfull with error message {string}")
    public void unsucessfullLogin(String expectedErrorMessage)  {
 
    	 String actualErrorMessage = driver.findElement(By.xpath("//*[@class='orangehrm-login-error']/div[1]/div[1]/p")).getText();

         // Verify Error Message
         Assert.assertEquals( expectedErrorMessage, actualErrorMessage);
 
    }
    
    @After
    public void teardown() {

        driver.quit();
    }
  
}

Step 11 – Create a Cucumber Runner class under src/test/java

It is recommended to create a package with a name such as org.example.cucumber.runner in src/test/java and create the CucumberRunnerTest (Runner) java file corresponding to that package.

We need to create a class called Runner class to run the tests. This class will use the JUnit annotation @RunWith(), which tells JUnit what is the test runner class.

package org.example.cucumber.runner;

import org.junit.runner.RunWith;

import io.cucumber.junit.Cucumber;
import io.cucumber.junit.CucumberOptions;

@RunWith(Cucumber.class)
@CucumberOptions(features = {
        "src/test/resources/features/LoginPage.feature" }, glue = "org.example.cucumber.definitions")
 
public class CucumberRunnerTest {

}

Step 12 – Test Execution through JUnit

Go to Runner class and right-click Run As JUnit. The tests will run as JUnit tests.

Step 13 – Run the tests from Command Line

Run the below command in the command prompt to run the tests and to get the test execution report.

mvn clean test

Step 14 – Cucumber Report Generation

To get Cucumber Test Reports, add cucumber.properties under src/test/resources and add the below instruction in the file

cucumber.publish.enabled=true

Below is the image of the Cucumber Report generated using the Cucumber Service

That’s it! Congratulations on making it through this tutorial and hope you found it useful! Happy Learning!!

How to manage driver executables using WebDriverManager

HOME

The traditional way to use any browser in Selenium tests is to download browser binaries, and we need to set the path of these files in our script like below or its location should be added to the classpath.

System.setProperty("webdriver.chrome.driver", "/absolute/path/to/binary/chromedriver");

The process of manually downloading and managing these drivers for each of the operating systems is very painful. We also have to check when new versions of the binaries are released / new browser versions are released. We should check the compatibility for all the executables and add them.

How to download all the driver executables automatically?

The automatic download of the drivers can be done by WebDriverManager. WebDriverManager is a library that allows controlling web browsers programmatically. It provides a cross-browser API that can be used to drive web browsers (e.g., Chrome, Edge, or Firefox, among others) using different programming languages (e.g., Java, JavaScript, Python, C#, or Ruby). The primary use of Selenium WebDriver is implementing automated tests for web applications.

The communication between the WebDriver API and the driver binary is done using a standard protocol called W3C WebDriver (formerly the so-called JSON Wire Protocol). Then, the communication between the driver and the browser is done using the native capabilities of each browser.

How To add WebDriverManager to a Selenium project manually?

Download the latest version of WebDriverManager from here.

It will download a zip file. Now extract the jar/zip file. It will show various .jar under the folder, as shown below:

Once we extract the zip file, we have to reference these jar files in our project. For this, navigate to project properties and click Build Path-> Configure Build Path in Eclipse

Click “Add External Jars” as per the steps highlighted below to include all the WebDriverManager jars extracted.

After clicking on the “Add External JARs“, all the selected extracted JARs are added to the project.

When this finishes, the project references show these referenced jars in the project explorer as highlighted below, and they are ready to be consumed in the Selenium test scripts.

Chrome

The below code snippet shows a quick usage of WebDriverManager with Chrome:

import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.chrome.ChromeOptions;

import io.github.bonigarcia.wdm.WebDriverManager;

public class Demo {

	public static void main(String[] args) {

		WebDriverManager.chromedriver().setup();

		// Create an object of Chrome Options class
		ChromeOptions chromeOptions = new ChromeOptions();

		// Create an object of WebDriver class and pass the Chrome Options object as
		// an argument
		WebDriver driver = new ChromeDriver(chromeOptions);

		System.out.println("Executing Chrome Driver");

		driver.get("https://www.bing.com/");
		System.out.println("Title of Page :" + driver.getTitle());
		System.out.println("Page URL : " + driver.getCurrentUrl());

		// Close the driver
		driver.close();

	}
}

The output of the above program is

FireFox Driver

The below code snippet shows a quick usage of WebDriverManager with FireFox:

import org.openqa.selenium.WebDriver;
import org.openqa.selenium.firefox.FirefoxDriver;
import org.openqa.selenium.firefox.FirefoxOptions;

import io.github.bonigarcia.wdm.WebDriverManager;

public class FireFoxDemo {

	public static void main(String[] args) {

		WebDriverManager.firefoxdriver().setup();

		// Create an object of Firefox Options class
		FirefoxOptions firefoxOptions = new FirefoxOptions();

	    // Create an object of WebDriver class and pass the Firefox Options object
		// as an argument
		WebDriver driver = new FirefoxDriver(firefoxOptions);

		System.out.println("Executing Firefox Driver");

		driver.get("https://www.bing.com/");
		System.out.println("Title of Page :" + driver.getTitle());
		System.out.println("Page URL : " + driver.getCurrentUrl());

		// Close the driver
		driver.close();

	}
}

The output of the above program is

Microsoft Edge

The below code snippet shows a quick usage of WebDriverManager with Microsoft Edge:

import org.openqa.selenium.WebDriver;
import org.openqa.selenium.edge.EdgeDriver;
import org.openqa.selenium.edge.EdgeOptions;
import io.github.bonigarcia.wdm.WebDriverManager;

public class EdgeDemo {

	public static void main(String[] args) {

		WebDriverManager.edgedriver().setup();

		// Create an object of Edge Options class
		EdgeOptions edgeOptions = new EdgeOptions();

		// Create an object of WebDriver class and pass the Edge Options object
		// as an argument
		WebDriver driver = new EdgeDriver(edgeOptions);

		System.out.println("Executing Microsoft Edge Driver");

		driver.get("https://www.bing.com/");
		System.out.println("Title of Page :" + driver.getTitle());
		System.out.println("Page URL : " + driver.getCurrentUrl());

		// Close the driver
		driver.close();

	}
}

The output of the above program is

The basic use of these managers is the following:

WebDriverManager.chromedriver().setup();
WebDriverManager.firefoxdriver().setup();
WebDriverManager.edgedriver().setup();
WebDriverManager.operadriver().setup();
WebDriverManager.chromiumdriver().setup()
WebDriverManager.iedriver().setup();

How To add WebDriverManager to a Selenium project using Maven or Gradle?

To use WebDriverManager in a Maven built project, the below-mentioned dependency is needed to add to the pom.xml.

<!-- https://mvnrepository.com/artifact/io.github.bonigarcia/webdrivermanager -->
<dependency>
    <groupId>io.github.bonigarcia</groupId>
    <artifactId>webdrivermanager</artifactId>
    <version>5.1.0</version>
</dependency>

For Gradle project, add the below to the build.gradle.

dependencies {
    testCompile("io.github.bonigarcia:webdrivermanager:5.1.0")
}

How to instantiate a specific browser version using WebDriverManager?

WebDriverManager provides the ability to download a specific version of the browser. For example, the latest chromedriver version is 100.0.4896.20 (released on 2022-03-04). But if we want an earlier version, say, Chromedriver version 98.0.4758.102, we have to add the following code.

import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.chrome.ChromeOptions;
import io.github.bonigarcia.wdm.WebDriverManager;

public class Demo {

	public static void main(String[] args) {

		WebDriverManager.chromedriver().driverVersion("98.0.4758.102").setup();

		// Create an object of Chrome Options class
		ChromeOptions chromeOptions = new ChromeOptions();

		// Create an object of WebDriver class and pass the Chrome Options object as
		// an argument
		WebDriver driver = new ChromeDriver(chromeOptions);

		System.out.println("Executing Chrome Driver");

		driver.get("https://www.bing.com/");
		System.out.println("Title of Page :" + driver.getTitle());
		System.out.println("Page URL : " + driver.getCurrentUrl());

		// Close the driver
		driver.close();

	}
}

The output of the above program is

As we can see from the above screenshot, as a result of executing the above program, the Chromedriver started successfully. We can see the details of starting the chrome driver instance in the first line of output. Here we have set the Chrome version to 98.0.4758.102″.

Congratulations!! We have learned to download drivers automatically.

How to run Chrome tests in headless mode in Selenium

HOME

This tutorial explains the steps to run the Selenium tests for Chrome browser in headless mode. We are going to run the tests in Selenium 4 as well as Selenium 3.

What is headless browser?

A headless browser is like any other browser, but without a Head/GUI (Graphical User Interface).  A headless browser is used to automate the browser without launching the browser. While the tests are running, we could not see the browser, but we can see the test results coming on the console.

Headless browser testing is generally faster when compared to actual UI testing as it doesn’t wait for the whole page to render before performing any action.

When we need to execute automated test cases remotely on a server or in any of the build and release pipelines for continuous integration servers like Gitlab or Jenkins, it is not always possible to install real browsers on such remote machines. We can use headless browsers to run automation tests efficiently.

It is easy to perform multi-tasking with a Headless browser. The browser or our machine can do anything else while the tests run in the background.

There are 2 ways to add dependencies to the Selenium project.

Download Selenium Version from here (Selenium 3 & Selenium 4)

Download ChromeDriver Binary (Selenium 3 only)

Download the latest version of WebDriverManager (Selenium 3 only)

Once the Selenium and WebDriverManager folders are downloaded, unzip the folder. Once the zip file is extracted, reference these jar files in the project. For this, navigate to project properties and click Build Path-> Configure Build Path in Eclipse. Click “Add External Jars“. After clicking on the “Add External JARs“, selected all the extracted JARs. The JARs files are present in the project.

2. Add the below dependencies to pom.xml or build.gradle.

Add below dependencies to the project.

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

package com.example.steps;

import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.chrome.ChromeOptions;
import org.openqa.selenium.firefox.FirefoxDriver;
import org.openqa.selenium.firefox.FirefoxOptions;

public class ChromeOptionsHeadless_Demo {

    public static void main(String[] args) {

        // Create an object of Chrome Options class
        ChromeOptions options = new ChromeOptions();

        // Set Firefox Headless mode as TRUE
        options.addArguments("--headless=new");

        // Create an object of WebDriver class and pass the Chrome Options object
        // as an argument
        WebDriver driver = new ChromeDriver(options);

        // Navigate to site url
        driver.get("https://duckduckgo.com/");

        System.out.println("Executing Chrome Driver in Headless mode..");
        System.out.println("Page Title : " + driver.getTitle());
        System.out.println("Page URL  : " + driver.getCurrentUrl());

        // Close the driver
        driver.quit();
    }

}

Add below dependencies to the project.

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

We know that to execute Selenium automation scripts on browsers like chrome or firefox, we must download the binary files of these drivers like chromedriver and geckodriver, etc. After this, we need to set the path to these binaries in the automation script or add the classpath location. Here, we want to execute Selenium WebDriver automation scripts on the Chrome browser, then you need first to download chromedriver.exe and then use the System.setProperty  method to set its path as follows:

	// Set the path of ChromeDriver
	System.setProperty("webdriver.chrome.driver",
				"C:\\Users\\Vibha\\Software\\chromedriver_win32_98.0.4758.102\\chromedriver.exe");

The complete program looks like as shown below:

import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.chrome.ChromeOptions;

public class ChromeOptionsHeadless1 {

	public static void main(String[] args) {

		// Set the path of ChromeDriver
		System.setProperty("webdriver.chrome.driver",
				"C:\\Users\\Vibha\\Software\\chromedriver_win32_98.0.4758.102\\chromedriver.exe");

		// Create an object of Chrome Options class
		ChromeOptions options = new ChromeOptions();

		// pass the argument –headless to Chrome Options class.
		options.addArguments("--headless");

		// Create an object of Chrome Driver class and pass the Chrome Options object as
		// an argument
		ChromeDriver driver = new ChromeDriver(options);

		System.out.println("Executing Chrome Driver in Headless mode..");
		driver.get("https://duckduckgo.com/");

		System.out.println("Title of Page :" + driver.getTitle());
		System.out.println("Page URL  : " + driver.getCurrentUrl());

		// Close the driver
		driver.close();

	}
}

How to run headless Chrome Tests in Selenium using WebDriverManager?

WebDriverManager

<!-- https://mvnrepository.com/artifact/io.github.bonigarcia/webdrivermanager -->
<dependency>
    <groupId>io.github.bonigarcia</groupId>
    <artifactId>webdrivermanager</artifactId>
    <version>5.1.0</version>
</dependency>

WebDriverManager has an automated way to download browser executables(exes) or binaries. It supports different browsers like Chrome, Firefox, Microsoft Edge, Internet Explorer, Opera, or PhantomJS.

WebDriverManager.chromedriver().setup: checks for the latest version of the specified WebDriver binary. If the binaries are not present on the machine, then it will download the WebDriver binaries. Next, it instantiates the Selenium WebDriver instance with the ChromeDriver.

import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.chrome.ChromeOptions;

import io.github.bonigarcia.wdm.WebDriverManager;

public class ChromeOptionsHeadless2 {

	public static void main(String[] args) {

		// WebDriverManager downloads chrome browser executables or binaries.
		WebDriverManager.chromedriver().setup();

		// Create an object of Chrome Options class
		ChromeOptions options = new ChromeOptions();

		// pass the argument –headless to Chrome Options class.
		options.addArguments("--headless");

		// Create an object of Chrome Driver class and pass the Chrome Options object as
		// an argument
		ChromeDriver driver = new ChromeDriver(options);

		System.out.println("Executing Chrome Driver in Headless mode..");
		driver.get("https://duckduckgo.com/");

		System.out.println("Title of Page :" + driver.getTitle());
		System.out.println("Page URL  : " + driver.getCurrentUrl());

		// Close the driver
		driver.close();

	}

}

Congratulations!! We are able to run Chrome tests in Selenium in headless mode.

How to run Firefox tests in headless mode in Selenium

HOME

This tutorial explains the steps to run the Selenium tests on Firefox browser in headless mode. We are going to run the tests in Selenium. To run the Selenium tests on Chrome browser in headless mode, refer this tutorial.

To start with, we need to add dependencies to the project.

Manually add the dependencies to the project

Download Selenium Version from here

Download Firefox Binary from here

Download the latest version of WebDriverManager (Download this if you want to use WebDriverManager to download browser executables(exes) or binaries automatically, then skip downloading FireFox Binary).

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

import org.openqa.selenium.WebDriver;
import org.openqa.selenium.firefox.FirefoxDriver;
import org.openqa.selenium.firefox.FirefoxOptions;

public class FirefoxOptionsHeadless_Demo {

    public static void main(String[] args) {

        // Create an object of Firefox Options class
        FirefoxOptions options = new FirefoxOptions();

        // Set Firefox Headless mode as TRUE
        options.addArguments("-headless");

        // Create an object of WebDriver class and pass the Firefox Options object
        // as an argument
        WebDriver driver = new FirefoxDriver(options);

        // Navigate to site url
        driver.get("https://duckduckgo.com/");

        System.out.println("Executing Firefox Driver in Headless mode..");
        System.out.println("Page Title : " + driver.getTitle());
        System.out.println("Page URL  : " + driver.getCurrentUrl());

        // Close the driver
        driver.quit();
    }

}

Add the below dependencies to pom.xml or build.gradle.

<!-- https://mvnrepository.com/artifact/org.seleniumhq.selenium/selenium-java -->
    <dependency>
      <groupId>org.seleniumhq.selenium</groupId>
      <artifactId>selenium-java</artifactId>
      <version>3.141.59</version>
    </dependency>

What is headless browser?

A headless browser is like any other browser, but without a GUI (Graphical User Interface).  A headless browser is used to automate the browser without launching the browser. While the tests are running, we could not see the browser, but we can see the test results coming on the console. This makes the test execution faster than normal execution. This is suitable for parallel testing as UI tests needs a lot of memory and resources.

import org.openqa.selenium.WebDriver;
import org.openqa.selenium.firefox.FirefoxDriver;
import org.openqa.selenium.firefox.FirefoxOptions;

public class FirefoxOptionsHeadless1 {

	public static void main(String[] args) {

		// Set the path of GeckoDriver
		System.setProperty("webdriver.gecko.driver",
				"C:\\Users\\Vibha\\Software\\geckodriver\\geckodriver.exe");

		// Create an object of Firefox Options class
		FirefoxOptions options = new FirefoxOptions();

		// Set Firefox Headless mode as TRUE
		options.setHeadless(true);

		// Create an object of WebDriver class and pass the Firefox Options object
		// as an argument
		WebDriver driver = new FirefoxDriver(options);

		// Navigate to site url
		driver.get("https://duckduckgo.com/");

		System.out.println("Executing Firefox Driver in Headless mode..");
		System.out.println("Page Title : " + driver.getTitle());
		System.out.println("Page URL  : " + driver.getCurrentUrl());

		// Close the driver
		driver.close();
	}
}

How to run headless Firefox Tests in Selenium using WebDriverManager?

WebDriverManager

<!-- https://mvnrepository.com/artifact/io.github.bonigarcia/webdrivermanager -->
<dependency>
    <groupId>io.github.bonigarcia</groupId>
    <artifactId>webdrivermanager</artifactId>
    <version>5.1.0</version>
</dependency>

WebDriverManager.firefoxdriver().setup(): checks for the latest version of the specified WebDriver binary. If the binaries are not present on the machine, then it will download the WebDriver binaries. In this case, it is not needed to download Firefox binary and set up the path

import org.openqa.selenium.WebDriver;
import org.openqa.selenium.firefox.FirefoxDriver;
import org.openqa.selenium.firefox.FirefoxOptions;

import io.github.bonigarcia.wdm.WebDriverManager;

public class FirefoxOptionsHeadless2 {

	public static void main(String[] args) {

		WebDriverManager.firefoxdriver().setup();

		// Create an object of Firefox Options class
		FirefoxOptions options = new FirefoxOptions();

		// Set Firefox Headless mode as TRUE
		options.setHeadless(true);

		// Create an object of Firefox Driver class and pass the Firefox Options object
		// as an argument
		WebDriver driver = new FirefoxDriver(options);

		// Navigate to the url
		driver.get("https://duckduckgo.com/");

		System.out.println("Executing Firefox Driver in Headless mode..");
		System.out.println("Page Title : " + driver.getTitle());
		System.out.println("Page URL  : " + driver.getCurrentUrl());

		// Close the driver
		driver.close();
	}

}

Congratulations!! We have run the tests in headless mode in FireFox.

How to handle Alerts in Selenium WebDriver

HOME

driver.switchTo().alert()

Below is a perfect example that shows how to handle Simple Alert with Selenium

import org.openqa.selenium.Alert;
import org.openqa.selenium.By;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.chrome.ChromeOptions;

import java.time.Duration;

public class SimpleAlert_Demo {
    public static void main(String[] args) throws InterruptedException {

        ChromeOptions options = new ChromeOptions();
        options.setImplicitWaitTimeout(Duration.ofSeconds(10));
        options.addArguments("start-maximized");
        ChromeDriver driver = new ChromeDriver(options);
        driver.navigate().to("https://the-internet.herokuapp.com/javascript_alerts");

        //Click on button to open Confirmation Box
        driver.findElement(By.xpath("//button[@onclick='jsAlert()']")).click();


        // accepting javascript alert
        Alert simpleAlert = driver.switchTo().alert();
        String alertText = simpleAlert.getText();

        //Print the message mentioned on the AlertBox
        System.out.println("Alert text is :" + alertText);

        //This step is only for demonstration purpose to show the alert box
        Thread.sleep(2000);
        simpleAlert.accept();

        //Close the current page
        driver.quit();
    }
}

2) Confirmation Alert

This alert comes with an option to accept or dismiss the alert. To accept the alert we can use Alert.accept() and to dismiss we can use the Alert.dismiss()

Below is an example that shows how to handle Confirmation Alert with Selenium.

import org.openqa.selenium.Alert;
import org.openqa.selenium.By;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.chrome.ChromeOptions;
import org.openqa.selenium.support.ui.ExpectedConditions;
import org.openqa.selenium.support.ui.WebDriverWait;
import java.time.Duration;

public class ConfirmationAlert_Demo {
    public static void main(String[] args) throws InterruptedException {

        ChromeOptions options = new ChromeOptions();
        options.setImplicitWaitTimeout(Duration.ofSeconds(10));
        options.addArguments("start-maximized");
        ChromeDriver driver = new ChromeDriver(options);
        driver.navigate().to("https://the-internet.herokuapp.com/javascript_alerts");

        //Click on button to open Confirmation Box
        driver.findElement(By.xpath("//button[@onclick='jsConfirm()']")).click();

        // accepting javascript alert
        Alert ConfirmationAlert = driver.switchTo().alert();
        String alertText = ConfirmationAlert.getText();
        System.out.println("Alert text is :" + alertText);
        ConfirmationAlert.accept();

        //Close the page
        driver.quit();
    }
}

3) Prompt Alert

In the prompt alert, we get an option to add text to the alert box. This is used when some input is required from the user. We will use the sendKeys() method to type something in the Prompt alert box. 

Below is an example that illustrates how to handle Prompt Alert using Selenium WebDriver.

import org.openqa.selenium.Alert;
import org.openqa.selenium.By;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.chrome.ChromeOptions;
import org.openqa.selenium.support.ui.ExpectedConditions;
import org.openqa.selenium.support.ui.WebDriverWait;

import java.time.Duration;

public class PromptAlert_Demo {
    public static void main(String[] args) throws InterruptedException {

        ChromeOptions options = new ChromeOptions();
        options.setImplicitWaitTimeout(Duration.ofSeconds(10));
        options.addArguments("start-maximized");
        ChromeDriver driver = new ChromeDriver(options);
        driver.navigate().to("https://the-internet.herokuapp.com/javascript_alerts");

        //Click on button to open Prompt Box
        driver.findElement(By.xpath("//button[@onclick='jsPrompt()']")).click();
        Alert promptAlert = driver.switchTo().alert();

        //Enter message in Alert Box
        promptAlert.sendKeys("Welcome to Selenium 4");
        promptAlert.accept();

        //This sleep is not necessary, just for demonstration
        Thread.sleep(2000);

        System.out.println("Prompt Alert text is :" + driver.findElement(By.id("result")).getText());

        //Close the current page
        driver.quit();
    }

}

That’s it! Congratulations on making it through this tutorial and hope you found it useful! Happy Learning!!

Actions Class in Selenium WebDriver

HOME

import org.openqa.selenium.interactions.Actions;
import org.openqa.selenium.interactions.Action;

How to get an instance of Actions class?

We can create an instance of Actions class simply, by passing current webDriver instance. Now, using the action instance, we can call any of the methods provided in Actions class.

WebDriver driver = new ChromeDriver();
Actions builder = new Actions(driver);

How to see all the supported methods by Actions class?

In order to see all the supported methods by Actions class, press control + space after, Action object (builder)

There is a large number of methods available in Actions class. The below screenshot represents some of those methods

Methods in Actions class of Selenium

There are many methods in this class, which can categorized into four main categories:

Different Methods for performing Keyboard Events:

1) keyDown(java.lang.CharSequence key) – Performs a modifier key press 

2) keyUp(java.lang.CharSequence key) – Performs a modifier key release

3) sendKeys(java.lang.CharSequence… keys) – Sends keys to the active element.

Different Methods for performing Mouse Events:

1) click() – Clicks at the current mouse location.

2) clickAndHold() – Clicks (without releasing) in the middle of the given element.

3) contextClick() – Performs a context-click at middle of the given element.

4) doubleClick() – Performs a double-click at the current mouse location.

7) dragAndDrop(WebElement source, WebElement target) – A convenience method that performs click-and-hold at the location of the source element, moves to the location of the target element, then releases the mouse.

8) dragAndDropBy(WebElement source, int xOffset, int yOffset) – A convenience method that performs click-and-hold at the location of the source element, moves by a given offset, then releases the mouse.

9) moveByOffset(int xOffset, int yOffset) – Moves the mouse from its current position or (0,0) by the given offset.

10) MoveToElement(WebElement target) – Moves the mouse to the middle of the element.