Hi, In this post, we'll learn about how to integrate Cucumber with Selenium, TestNG and Maven.
This is as part of a project that we wanted to migrate the UI automation from Junit frame work to TestNG and we also wanted to upgrade to the latest versions of the dependencies.
For the demo, we will use the HRM website.
https://opensource-demo.orangehrmlive.com/index.php/auth/login
Username : Admin, Password: admin123
Test Cases/Scenarios:
Cucumber features:
- How to implement data driven approach using DataTable object in Login scenario ?
- How to use Background keyword in feature files to to login for each scenario except for Login?
(keep the tests independent of each other) - How to give Tags(single and multiple tags) in CucumberOptions in RunCucumberTest class?
- How to use Cucumber Before and After Hooks for each scenario ?
- Online cucumber report
Selenium features:
- Implicit wait with Duration of times
- Explicit wait with Duration of times
- findElements , add elments to List<WebElement>, display the list elements, size of the list
TestNG and Maven features:
- Assertions used in this demo are from TestNG framework.
- How to configure testng.xml file in pom.xml in the maven-surefire-plugin ?
- How to run the cucumber scenarios from command line ?
Let's begin!
i.e., the usage of src/test/java and src/test/resources
- cucumber-java 7.1.0
- cucumber-testng 7.1.0
- selenium 4.3.0
- testng 7.1.0
- maven-surefire-plugin 3.0.0-M7
- maven-compiler-plugin 3.10.1
- Maven installed in Windows is 3.8.6
Project Structure:
Source code : GitHub or download this zip
Watch, the no voice walk-through video tutorial on YouTube
Now, the steps:
- Download and install Cucumber plug-in in Eclipse from Market Place
- Download and install TestNG plug-in in Eclipse from Market Place
- Create a new Maven project (say : CucucumberTestNGSeleniumMavenCommandLine)
- Add cucumber-java, cucumber-testng, testng and selenium dependencies in the pom.xml and etc.
- Add Maven compiler plugin, maven-surefire-plugin in pom.xml
- Create feature files(Gherkhin script) in src/test/resources folder
- Write java, selenium, glue(step definitions), cucumber testng runner class in src/test/java folder
- BasePage class for driver
- Hooks class for cucumber Before and After hooks.
- Step Definition Or Glue Code for the feature files
- Cucumber & TestNG runner class, RunCucumberTest.java
- Create testng.xml for the project and configure it in pom.xml
- Run Tests from TestNG Tests
- Run Tests from testng.xml
- Run Tests from command line
- Test results analysis from Cucumber report
- Test results analysis from TestNG report
Step 1: Download and install Cucumber plug-in in Eclipse from Market Place
Install the cucumber plug in from the market place.
Step 2: Download and install TestNG plug-in in Eclipse from Market Place
Install the cucumber plug in from the market place.
Step 3: Download and install TestNG plug-in in Eclipse from Market Place
Refer to the above image : Project Structure (It should be a maven project)Step 4: Add cucumber-java, cucumber-testng, testng and selenium dependencies in the pom.xml and etc. and
Step 5: Add Maven compiler plugin, maven-surefire-plugin in pom.xml
<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 https://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>Cucumber7-TestNG7-Selenium4-OrnageHRM-POC2</groupId> <artifactId>Cucumber7-TestNG7-Selenium4-OrnageHRM-POC2</artifactId> <version>0.0.1-SNAPSHOT</version> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> </properties> <dependencies> <!-- https://mvnrepository.com/artifact/io.cucumber/cucumber-java --> <dependency> <groupId>io.cucumber</groupId> <artifactId>cucumber-java</artifactId> <version>7.1.0</version> </dependency> <!-- https://mvnrepository.com/artifact/io.cucumber/cucumber-java --> <!-- https://mvnrepository.com/artifact/io.cucumber/cucumber-testng --> <dependency> <groupId>io.cucumber</groupId> <artifactId>cucumber-testng</artifactId> <version>7.1.0</version> </dependency> <!-- https://mvnrepository.com/artifact/org.seleniumhq.selenium/selenium-java --> <dependency> <groupId>org.seleniumhq.selenium</groupId> <artifactId>selenium-java</artifactId> <version>4.3.0</version> </dependency> <!-- https://mvnrepository.com/artifact/org.testng/testng --> <dependency> <groupId>org.testng</groupId> <artifactId>testng</artifactId> <version>7.1.0</version> </dependency> <!-- https://mvnrepository.com/artifact/org.apache.maven.plugins/maven-compiler-plugin --> </dependencies> <build> <pluginManagement> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-surefire-plugin</artifactId> <version>3.0.0-M7</version> <configuration> <suiteXmlFiles> <suiteXmlFile>testng.xml</suiteXmlFile> </suiteXmlFiles> </configuration> </plugin> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <version>3.10.1</version> <configuration> <source>1.8</source> <target>1.8</target> <encoding>UTF-8</encoding> </configuration> </plugin> </plugins> </pluginManagement> </build> </project>
Step 6: Create feature files(Gherkhin script) in src/test/resources folder
@HRMLogin Feature: Login to HRM Application I want to use this template for HRM Login page @LoginValidCredentials Scenario: LoginValidCredentials Given User login to HRM application with UserName and Password | Admin | admin123 | Then User navigates to Dashboard page
Dashboard.feature
@Dasbhoard Feature: Dashboard page I want to use this template for my Dashboard Page Background: Given User login to HRM application with UserName and Password | Admin | admin123 | @DashboardTabCountOfQuickLaunhElements Scenario: DashboardTabCountOfQuickLaunhElements Then User finds the list of quick launch elements @DirectoryTabNavigationFromDashboardTab Scenario: DirectoryTabNavigationFromDashboardTab Then User clicks on Directory tab and verifies the navigation
@Directory Feature: Dashboard page I want to use this template for my Directory Page Background: Given User login to HRM application with UserName and Password | Admin | admin123 | @DirectoryTabIsSearchButtonDisplayed Scenario: DirectoryTabIsSearchButtonDisplayed Then User is on Directory page Then Is Search button displayed
Step 7: Write java, selenium, glue(step definitions), cucumber testng runner class in src/test/java folder
Define the web driver in this call and use it as super class for the step definition classes or in the Hooks class.
Hooks class for cucumber Before and After hooks.
Since it is a repeated activity for each scenario, we keep it in this Hook which means that the code that we write in Before Hook is executed/called before the execution of each scenario.
We can do this in Background band in the feature files as well.
Step Definition Or Glue Code for the feature files
Write the glude code or step definitions code for each scenario in the HRMLoginPage.java, Dashboard.java and Directory.java files.
Cucumber & TestNG runner class, RunCucumberTest.java
tags="@LoginValidCredentials and not @DashboardTabCountOfQuickLaunhElements
and not @DirectoryTabNavigationFromDashboardTab
or @DirectoryTabIsSearchButtonDisplayed",
BasePage.java
package com.sadakar.common; import org.openqa.selenium.WebDriver; public class BasePage { public static WebDriver driver; }
Hooks.java
package com.sadakar.common; import org.openqa.selenium.chrome.ChromeDriver; import io.cucumber.java.After; import io.cucumber.java.Before; public class Hooks extends BasePage { @Before public static void setupDriver() throws InterruptedException { System.setProperty("webdriver.chrome.driver", "D:\\chromedriver.exe"); driver = new ChromeDriver(); driver.manage().window().maximize(); driver.get("https://opensource-demo.orangehrmlive.com/index.php/auth/login"); } @After public static void quitDriver() throws Exception { driver.quit(); } }
HRMLoginPage.java
package com.sadakar.stepdefinitions; import java.time.Duration; import java.util.List; import org.openqa.selenium.By; import org.openqa.selenium.WebElement; import org.openqa.selenium.support.ui.ExpectedConditions; import org.openqa.selenium.support.ui.WebDriverWait; import org.testng.Assert; import com.sadakar.common.BasePage; import io.cucumber.java.en.Given; import io.cucumber.java.en.Then; public class HRMLoginPage extends BasePage { @Given("User login to HRM application with UserName and Password") public void loginToHRMApp(io.cucumber.datatable.DataTable dataTable) { List<List<String>> cells = dataTable.cells(); driver.findElement(By.xpath("//*[@id=\"txtUsername\"]")).sendKeys(cells.get(0).get(0)); driver.findElement(By.xpath("//*[@id=\"txtPassword\"]")).sendKeys(cells.get(0).get(1)); driver.findElement(By.id("btnLogin")).submit(); driver.manage().timeouts().implicitlyWait(Duration.ofSeconds(5)); } @Then("User navigates to Dashboard page") public void navigateToDashboardTab() { WebDriverWait wait = new WebDriverWait(driver,Duration.ofSeconds(10)); wait.until(ExpectedConditions.visibilityOfElementLocated(By.xpath("//*[@id=\"menu_dashboard_index\"]"))); WebElement dashboardLabel = driver.findElement(By.xpath("//*[@id=\"content\"]/div/div[1]/h1")); Assert.assertTrue(dashboardLabel.isDisplayed()); } }
DashboardPage.java
package com.sadakar.stepdefinitions; import java.time.Duration; import java.util.List; import org.openqa.selenium.By; import org.openqa.selenium.WebElement; import com.sadakar.common.BasePage; import io.cucumber.java.en.Then; public class DashboardPage extends BasePage { @Then("User finds the list of quick launch elements") public void listOfQuickLaunchElementsOnDashboardPage() { // Adding table data of a row to WebElement List List<WebElement> actualListOfQuickLaunchElements = driver .findElements(By.xpath("//*[@id=\"dashboard-quick-launch-panel-menu_holder\"]/table/tbody/tr/td")); // Display the table data of row from the WebElementList for (WebElement ele : actualListOfQuickLaunchElements) { System.out.println(ele.getText()); } // Display the size of WebElement List System.out.println("Size of Quick launch elements : " + actualListOfQuickLaunchElements.size()); } @Then("User clicks on Directory tab and verifies the navigation") public void navigateToDirectoryTabFromDashbaordTab() { driver.manage().timeouts().implicitlyWait(Duration.ofSeconds(5)); driver.findElement(By.xpath("//*[@id=\"menu_directory_viewDirectory\"]")).click(); } }
DirectoryPage.java
package com.sadakar.stepdefinitions; import java.time.Duration; import org.openqa.selenium.By; import org.openqa.selenium.WebElement; import org.testng.Assert; import com.sadakar.common.BasePage; import io.cucumber.java.en.Then; public class DirectoryPage extends BasePage{ @Then("User is on Directory page") public void directoryPage() { driver.findElement(By.xpath("//*[@id=\"menu_directory_viewDirectory\"]")).click(); driver.manage().timeouts().implicitlyWait(Duration.ofSeconds(5)); } @Then("Is Search button displayed") public void isSearchButtonDisplayed() { WebElement searchButton = driver.findElement(By.xpath("//*[@id=\"searchBtn\"]")); Assert.assertTrue(searchButton.isDisplayed()); } }
RunCucumberTest.java
package com.sadakar.testng.runner; import io.cucumber.testng.AbstractTestNGCucumberTests; import io.cucumber.testng.CucumberOptions; @CucumberOptions( //tags="@LoginValidCredentials", //tags="@DashboardTabCountOfQuickLaunhElements", //tags="@DirectoryTabNavigationFromDashboardTab", //tags="@DirectoryTabIsSearchButtonDisplayed", tags="@LoginValidCredentials or @DashboardTabCountOfQuickLaunhElements or @DirectoryTabNavigationFromDashboardTab or @DirectoryTabIsSearchButtonDisplayed", //tags="@LoginValidCredentials and not @DashboardTabCountOfQuickLaunhElements and not @DirectoryTabNavigationFromDashboardTab and not @DirectoryTabIsSearchButtonDisplayed", features = "classpath:features", glue = {"com.sadakar.common", "com.sadakar.stepdefinitions", "com.sadakar.testng.runner"}, plugin = { "pretty", "json:target/cucumber-reports/cucumber.json", "html:target/cucumber-reports/cucumberreport.html" }, monochrome = true) public class RunCucumberTest extends AbstractTestNGCucumberTests { }
Step 8: Create testng.xml for the project and configure it in pom.xml
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE suite SYSTEM "https://testng.org/testng-1.0.dtd"> <suite name="Suite"> <test name="Test"> <classes> <class name="com.sadakar.testng.runner.RunCucumberTest"/> </classes> </test> </suite>
[RemoteTestNG] detected TestNG version 7.0.1 @Dasbhoard @DashboardTabCountOfQuickLaunhElements Scenario: DashboardTabCountOfQuickLaunhElements # features/Dashboard.feature:9 SLF4J: Failed to load class "org.slf4j.impl.StaticLoggerBinder". SLF4J: Defaulting to no-operation (NOP) logger implementation SLF4J: See http://www.slf4j.org/codes.html#StaticLoggerBinder for further details. Starting ChromeDriver 103.0.5060.53 (a1711811edd74ff1cf2150f36ffa3b0dae40b17f-refs/branch-heads/5060@{#853}) on port 50670 Only local connections are allowed. Please see https://chromedriver.chromium.org/security-considerations for suggestions on keeping ChromeDriver safe. ChromeDriver was started successfully. Jul 06, 2022 12:49:38 PM org.openqa.selenium.remote.ProtocolHandshake createSession INFO: Detected upstream dialect: W3C Jul 06, 2022 12:49:38 PM org.openqa.selenium.devtools.CdpVersionFinder findNearestMatch INFO: Found exact CDP implementation for version 103 Given User login to HRM application with UserName and Password # com.sadakar.stepdefinitions.HRMLoginPage.loginToHRMApp(io.cucumber.datatable.DataTable) | Admin | admin123 | Assign Leave Leave List Timesheets Apply Leave My Leave My Timesheet Size of Quick launch elements : 6 Then User finds the list of quick launch elements # com.sadakar.stepdefinitions.DashboardPage.listOfQuickLaunchElementsOnDashboardPage() @Dasbhoard @DirectoryTabNavigationFromDashboardTab Scenario: DirectoryTabNavigationFromDashboardTab # features/Dashboard.feature:13 Starting ChromeDriver 103.0.5060.53 (a1711811edd74ff1cf2150f36ffa3b0dae40b17f-refs/branch-heads/5060@{#853}) on port 52607 Only local connections are allowed. Please see https://chromedriver.chromium.org/security-considerations for suggestions on keeping ChromeDriver safe. ChromeDriver was started successfully. Jul 06, 2022 12:49:51 PM org.openqa.selenium.remote.ProtocolHandshake createSession INFO: Detected upstream dialect: W3C Jul 06, 2022 12:49:51 PM org.openqa.selenium.devtools.CdpVersionFinder findNearestMatch INFO: Found exact CDP implementation for version 103 Given User login to HRM application with UserName and Password # com.sadakar.stepdefinitions.HRMLoginPage.loginToHRMApp(io.cucumber.datatable.DataTable) | Admin | admin123 | Then User clicks on Directory tab and verifies the navigation # com.sadakar.stepdefinitions.DashboardPage.navigateToDirectoryTabFromDashbaordTab() @Directory @DirectoryTabIsSearchButtonDisplayed Scenario: DirectoryTabIsSearchButtonDisplayed # features/Directory.feature:10 Starting ChromeDriver 103.0.5060.53 (a1711811edd74ff1cf2150f36ffa3b0dae40b17f-refs/branch-heads/5060@{#853}) on port 64336 Only local connections are allowed. Please see https://chromedriver.chromium.org/security-considerations for suggestions on keeping ChromeDriver safe. ChromeDriver was started successfully. Jul 06, 2022 12:50:11 PM org.openqa.selenium.remote.ProtocolHandshake createSession INFO: Detected upstream dialect: W3C Jul 06, 2022 12:50:11 PM org.openqa.selenium.devtools.CdpVersionFinder findNearestMatch INFO: Found exact CDP implementation for version 103 Given User login to HRM application with UserName and Password # com.sadakar.stepdefinitions.HRMLoginPage.loginToHRMApp(io.cucumber.datatable.DataTable) | Admin | admin123 | Then User is on Directory page # com.sadakar.stepdefinitions.DirectoryPage.directoryPage() Then Is Search button displayed # com.sadakar.stepdefinitions.DirectoryPage.isSearchButtonDisplayed() @HRMLogin @LoginValidCredentials Scenario: LoginValidCredentials # features/HRMLogin.feature:6 Starting ChromeDriver 103.0.5060.53 (a1711811edd74ff1cf2150f36ffa3b0dae40b17f-refs/branch-heads/5060@{#853}) on port 56598 Only local connections are allowed. Please see https://chromedriver.chromium.org/security-considerations for suggestions on keeping ChromeDriver safe. ChromeDriver was started successfully. Jul 06, 2022 12:50:32 PM org.openqa.selenium.remote.ProtocolHandshake createSession INFO: Detected upstream dialect: W3C Jul 06, 2022 12:50:32 PM org.openqa.selenium.devtools.CdpVersionFinder findNearestMatch INFO: Found exact CDP implementation for version 103 Given User login to HRM application with UserName and Password # com.sadakar.stepdefinitions.HRMLoginPage.loginToHRMApp(io.cucumber.datatable.DataTable) | Admin | admin123 | Then User navigates to Dashboard page # com.sadakar.stepdefinitions.HRMLoginPage.navigateToDashboardTab() ???????????????????????????????????????????????????????????????????????????? ? View your Cucumber Report at: ? ? https://reports.cucumber.io/reports/bebe12f4-ffa5-46a1-a8e2-11ea5d3ef259 ? ? ? ? This report will self-destruct in 24h. ? ? Keep reports forever: https://reports.cucumber.io/profile ? ????????????????????????????????????????????????????????????????????????????PASSED: runScenario("DashboardTabCountOfQuickLaunhElements", "Optional[Dashboard page]") Runs Cucumber Scenarios PASSED: runScenario("DirectoryTabNavigationFromDashboardTab", "Optional[Dashboard page]") Runs Cucumber Scenarios PASSED: runScenario("DirectoryTabIsSearchButtonDisplayed", "Optional[Dashboard page]") Runs Cucumber Scenarios PASSED: runScenario("LoginValidCredentials", "Optional[Login to HRM Application]") Runs Cucumber Scenarios =============================================== Default test Tests run: 4, Failures: 0, Skips: 0 =============================================== =============================================== Default suite Total tests run: 4, Passes: 4, Failures: 0, Skips: 0 ===============================================
No comments:
Post a Comment