We can create a JSON Object using a Map in Java. A JSON Object is a key-value pair and can be easily created using a Java Map. A Map in Java also represents a collection of key-value pairs.
To create a request body using JSON Object using HashMap, we need to add a Maven dependency.
I have created a simple Java map and filled it with the values that represent JSON properties.
import io.restassured.RestAssured;
import io.restassured.http.ContentType;
import org.junit.Test;
import java.util.HashMap;
import java.util.Map;
import static org.hamcrest.Matchers.equalTo;
public class Json_Demo {
@Test
public void passBodyAsMap() {
Map<String, String> map = new HashMap<String, String>();
map.put("employee_name", "MapTest");
map.put("employee_salary", "99999");
map.put("employee_age", "30");
map.put("profile_image", "test.png");
RestAssured.given()
.contentType(ContentType.JSON)
.body(map)
.log().all()
.when()
.post("https://dummy.restapiexample.com/api/v1/create")
.then()
.assertThat().statusCode(200)
.body("data.employee_name", equalTo("MapTest"))
.body("data.employee_age", equalTo("30"))
.body("data.employee_salary", equalTo("99999"))
.body("message", equalTo("Successfully! Record has been added.")).log().all();
}
}
The request body as well as the response body will look as shown below:-
Above one is a simple JSON Request Body. Let us take an example of a Complex Request Body or nested Request Body as shown below.
Let us create a Java program to understand this:
import io.restassured.RestAssured;
import io.restassured.http.ContentType;
import org.junit.Test;
import java.util.HashMap;
import java.util.Map;
import static org.hamcrest.Matchers.equalTo;
public class Json_Demo {
@Test
public void passBodyAsMultipleMap() {
// First JSON Object using Hash Map
Map<String, Object> data = new HashMap<String, Object>();
data.put("employee_name", "MapTest");
data.put("profile_image", "test.png");
// Second JSON Object using Hash Map
Map<String, String> msg = new HashMap<String, String>();
msg.put("updated_message", "Details of New Resource");
msg.put("employee_age", "30");
data.put("details", msg);
data.put("employee_salary", "99999");
RestAssured.given().contentType(ContentType.JSON).body(data).log().all()
// WHEN
.when().post("https://dummy.restapiexample.com/api/v1/create")
// THEN
.then().assertThat().statusCode(200).body("data.employee_name", equalTo("MapTest"))
.body("data.details.updated_message", equalTo("Details of New Resource"))
.body("data.details.employee_age", equalTo("30")).body("data.employee_salary", equalTo("99999"))
.body("message", equalTo("Successfully! Record has been added.")).log().all();
}
}
The request body as well as the response body will look as shown below image. The first part is the body of the request and the second part is the response provided by the API.
Congratulations on making it through this tutorial and hope you found it useful! Happy Learning!!
Cucumber is a BDD Tool, and Selenium WebDriver is used for the automation of web applications. Imagine we need to build a test framework. This framework can be used by businesses to understand the test scenarios. It can also test the web application. This can be achieved by integrating Cucumber with Selenium. I’m going to use TestNG as the Test Automation tool for assertions. In the previous tutorial, I used Cucumber with Page Object Model. To know more about this, please refer to this tutorial – Page Object Model with Selenium, Cucumber, and TestNG.
In this tutorial, I’ll create a BDD Framework for the testing of web applications. I will use Cucumber, Selenium WebDriver, Maven and TestNG.
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, which is needed to write Java code. 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.
The Cucumber Eclipse plugin is a plugin that allows eclipse to understand the Gherkin syntax. The Cucumber Eclipse Plugin highlights the keywords present in Feature File. Click here to know more – How to install Cucumber Eclipse Plugin
Group Id – com.example Artifact Id – Cucumber_TestNG_Demo Version – 0.0.1-SNAPSHOT Package – com. example. Cucumber_TestNG_Demo
Step 7 – Create source folder src/test/resources to create test scenarios in Feature file
When a new Maven Project is created, it has 2 folders – src/main/java and src/test/java as shown below image. 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.
Step 8 – Add Selenium, TestNG, and Cucumber dependencies to the project
Add the below-mentioned Selenium, TestNG, and Cucumber dependencies to the project.
Step 9 – Add Maven Compiler Plugin and SureFire 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:
If you don’t add a compiler plugin to the POM.xml, the build will fail. This happens when you try to run the tests through Maven. Then the build will fail with the below message.
Step 10 – Create a feature file under src/test/resources/features
It is recommended to create a features folder in the src/test/resources directory. Create all the feature files in this features folder. Feature file should be saved as an extension of .feature. The test scenarios in the Feature file are written in Gherkins language. Add the test scenarios in this feature file. I have added sample test scenarios.
Feature: Login to HRM Application
Background:
Given User is on HRMLogin page "https://opensource-demo.orangehrmlive.com/"
@ValidCredentials
Scenario: Login with valid credentials
When User enters username as "Admin" and password as "admin123"
Then User should be able to login sucessfully and new page open
@InvalidCredentials
Scenario Outline: Login with invalid credentials
When User enters username as "<username>" and password as "<password>"
Then User should be able to see error message "<errorMessage>"
Examples:
| username | password | errorMessage |
| Admin | admin12$$ | Invalid credentials |
| admin$$ | admin123 | Invalid credentials |
| abc123 | xyz$$ | Invalid credentials |
Step 11 – Create the step definition class in src/test/java
Create the step definition class corresponding to the feature file to test the scenarios in the src/test/java directory. The StepDefinition files should be created in this definitionsdirectory within the folder called definitions.
Below is the step definition of the LoginPage feature file.
package com.example.definitions;
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 io.github.bonigarcia.wdm.WebDriverManager;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.chrome.ChromeOptions;
import org.testng.Assert;
import java.time.Duration;
public class LoginPageDefinitions {
private static WebDriver driver;
public final static int TIMEOUT = 5;
@Before
public void setUp() {
ChromeOptions options = new ChromeOptions();
options.addArguments("--start-maximized");
driver = new ChromeDriver(options);
driver.manage().timeouts().implicitlyWait(Duration.ofSeconds(TIMEOUT));
}
@Given("User is on HRMLogin page {string}")
public void loginTest(String url) {
driver.get(url);
}
@When("User enters username as {string} and password as {string}")
public void goToHomePage(String userName, String passWord) {
// login to application
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 verifyLogin() {
String homePageHeading = driver.findElement(By.xpath("//*[@class='oxd-topbar-header-breadcrumb']/h6")).getText();
//Verify new page - HomePage
Assert.assertEquals(homePageHeading, "Dashboard");
}
@Then("User should be able to see error message {string}")
public void verifyErrorMessage(String expectedErrorMessage) {
String actualErrorMessage = driver.findElement(By.xpath("//*[@class='orangehrm-login-error']/div[1]/div[1]/p")).getText();
// Verify Error Message
Assert.assertEquals(actualErrorMessage, expectedErrorMessage);
}
@After
public void teardown() {
driver.quit();
}
}
assertThat() and containsString are imported from package:-
Step 12 – Create a TestNG Cucumber Runner classin src/test/java
We need to create a class called Runner class to run the tests. This class will use the TestNG annotation @RunWith(), which tells TestNG what is the test runner class. TestRunner should be created under src/test/java within the folder called runner.
Below is the code for the Cucumber Runner Class.
import io.cucumber.testng.AbstractTestNGCucumberTests;
import io.cucumber.testng.CucumberOptions;
@CucumberOptions(tags = "", features = {"src/test/resources/features/LoginPage.feature"}, glue = {"com.example.definitions"},
plugin = {})
public class CucumberRunnerTests extends AbstractTestNGCucumberTests {
}
AbstractTestNGCucumberTests – Runs each cucumber scenario found in the features as a separate test.
Step 13 – Test Execution through TestNG
Go to the Runner class and right-click “Run As TestNG Test”. The tests will run as TestNG tests. This is for Eclipse.
In case you are using IntelliJ, then select “Run CucumberRunner Tests“.
This is what the execution console will look like in Eclipse.
Step 14 – Run the tests from TestNG.xml
Create a TestNG.xml as shown below and run the tests as TestNG.
Below is an example of testng.xml.
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE suite SYSTEM "https://testng.org/testng-1.0.dtd">
<suite name="Suite">
<test name="Cucumber with TestNG Test">
<classes>
<class name="com.example.runner.CucumberRunnerTests"/>
</classes>
</test> <!-- Test -->
</suite> <!-- Suite -->
Step 15 – Run the tests from the Command Line
Run the below command in the command prompt to run the tests and to get the test execution report.
mvn clean test
The execution screen looks like something as shown below.
Step 16 – Cucumber Report Generation
Add cucumber.properties under src/test/resources and add the below instructions in the file.
cucumber.publish.enabled=true
Below is the image of the Cucumber Report generated using the Cucumber Service.
Step 17 – TestNG Report Generation
TestNG generates various types of reports under the test-output or target folder like emailable-report.html, index.html, testng-results.xml.
We are interested in the ‘emailable-report.html’ report. Open “emailable-report.html“, as this is an HTML report, and open it with the browser. The below image shows emailable-report.html.
emailable-report.html
Index.html
TestNG also produces “index.html” report, and it resides under the test-output folder. The below image shows the index.html report.
CI/CD Integration:
Integrating BDD tests with Continuous Integration and Continuous Deployment (CICD) pipelines helps automate the testing process. Tools like Jenkins, GitLab CI, or GitHub Actions can be configured easily. They run BDD tests automatically during the build process. Here’s how:
Configure the CICD Pipeline:Set up the pipeline to build the project, run tests, and create reports.
Run Tests: Ensure the pipeline runs your BDD tests using Maven or Gradle.
Publish Reports: Configure the pipeline to show test results, so you can easily see if there are any issues.
Troubleshooting Tips:
1. Maven Dependencies Not Resolved: The dependencies for Cucumber, Selenium, or TestNG are not resolving in your project. Make sure your pom.xml is correctly configured and the Maven repository has the latest dependencies. Run mvn clean install to force update dependencies. Also, check if you have internet access and the correct settings in your Maven configuration.
2. TestNG XML File Setup: TestNG tests are not running as expected, or the test results are incorrect. Double-check your `testng.xml` configuration to ensure that the correct test classes, packages, or methods are included. Make sure annotations like `@Test` are correctly used in your test classes.
3. Cucumber Features Not Recognized: Cucumber feature files aren’t recognized by your test runner. Verify your `CucumberOptions` in the test runner class points to the correct `features` path and `glue` path for step definitions. Make sure your feature files have the correct `.feature` extension and contain valid Gherkin syntax.
We may quickly validate the steps in your feature using Dry Run in Cucumber, without having to run the code inside the appropriate step definitions, to ensure that every Step has its corresponding Step Definition present in the Step Definition file. A cucumber dry run is used to confirm the compilation faults and compile the Step Definition and Feature files. It is a way to validate the correctness of the Gherkin syntax in the feature files and the mapping of steps defined in the step definitions without executing the actual application code.
The Dry Run option can either be set as true or false. By default, it is false.
Dry Run as true
import io.cucumber.testng.AbstractTestNGCucumberTests;
import io.cucumber.testng.CucumberOptions;
@CucumberOptions(plugin = {"pretty"},
features = "src/test/resources/Features",
glue = "org.example.stepdefinitions",
monochrome=true,
dryRun = true)
public class CucumberRunnerTests extends AbstractTestNGCucumberTests {
}
Below is the sample feature file.
Feature: Login to HRM Application
@ValidCredentials
Scenario: Login with valid credentials
Given User is on HRMLogin page "https://opensource-demo.orangehrmlive.com/"
When User enters username as "Admin" and password as "admin123"
Then User should be able to login successfully and new page open
In the below snippet of code, I have created the stepdefinitions for the Given and When statements and no stepdefinition for the Then statement.
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 io.github.bonigarcia.wdm.WebDriverManager;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;
import org.testng.Assert;
import java.time.Duration;
public class LoginPageDefinitions {
private static WebDriver driver;
public final static int TIMEOUT = 5;
@Before
public void setUp() {
WebDriverManager.chromedriver().setup();
ChromeOptions options = new ChromeOptions();
options.addArguments("--start-maximized");
driver = new ChromeDriver(options);
driver.manage().timeouts().implicitlyWait(Duration.ofSeconds(TIMEOUT));
}
@Given("User is on HRMLogin page {string}")
public void loginTest(String url) {
driver.get(url);
}
@When("User enters username as {string} and password as {string}")
public void goToHomePage(String userName, String passWord) {
// login to application
driver.findElement(By.name("username")).sendKeys(userName);
driver.findElement(By.name("password")).sendKeys(passWord);
driver.findElement(By.xpath("//*[@id='app']/div[1]/div/div[1]/div/div[2]/div[2]/form/div[3]/button")).submit();
// go the next page
}
@After
public void teardown() {
driver.quit();
}
}
Execute the feature file by right-clicking on the Runner class and selecting – Run As TestNG Test.
In the case of the dry run as true, none of the Steps is executed, but Cucumber has only made sure that every Step has the interconnected method available in the Step Definition file. Take a look at the time duration at the end of every Step. It is extremely less.
The output of the above program is
Dry Run as false
In the below case, dryRun is false.
import io.cucumber.testng.AbstractTestNGCucumberTests;
import io.cucumber.testng.CucumberOptions;
@CucumberOptions(plugin = {"pretty"},
features = "src/test/resources/Features",
glue = "org.example.stepdefinitions",
monochrome=true,
dryRun = false)
public class CucumberRunnerTests extends AbstractTestNGCucumberTests {
}
The output of the above program is
In case of dry run as false, the steps 1 and 2 will be executed. The browser will open and all statements inside the step definitions method will execute when set to false. The time taken to complete this test is 0.235 sec.
So, you can set dry run to true to quickly check if any of the step definition is not implemented.
In the previous tutorial, I explained theSerenity BDD with Cucumber for Web Application using Junit4. In this tutorial, I will explain the parallel execution of Cucumber Scenarios with Serenity and JUnit5. This tutorial gives a clear picture of the initial setup of a BDD Framework.
Starting with version 3.6.0 is possible to run the Cucumber scenarios in parallel.
We need to mention these in the junit-platform.properties to run the Cucumber scenarios parallelly.
Step 2 – Download and setup Eclipse IDE on the system
The Eclipse IDE (integrated development environment) provides strong support for Java developers which is needed to write Java code. Click here to know How to install Eclipse.
Step 3 – Setup Maven and create a new Maven Project
Group Id – org.example Artifact Id – ParallelTests_Serenity_Cucumber_Junit5_Demo Version – 0.0.1-SNAPSHOT Package – org.example. ParallelTests_Serenity_Cucumber_Junit5_Demo
Step 4 – Update Properties section in Maven pom.xml
Step 7 – Create a feature file in src/test/resources
The purpose of the Feature keyword is to provide a high-level description of a software feature and to group related scenarios. To know more about the Feature files, please refer this tutorial.
Feature: Login to HRM
@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 successfully
@InValidCredentials
Scenario: Login with invalid credentials
Given User is on Home page
When User enters username as "Admin1"
And User enters password as "Admin123"
Then User should be able to see error message "Invalid credentials"
@BlankUsername
Scenario: Login with blank username
Given User is on Home page
When User enters username as ""
And User enters password as "Admin123"
Then User should be able to see error message "Required" below username
Step 8 – Create the Step pages for StepDefinition class
In Serenity, tests are broken down into reusable steps. An important principle behind Serenity is the idea that it is easier to maintain a test that uses several layers of abstraction to hide the complexity behind different parts of a test. So, in Step class, we will declare the locators of the web elements and the actions performed on these web elements.
There are multiple ways to identify a web element on the web page – one of the ways is to use @FindBy or $(By.).
I prefer to use @FindBy as I do need not to find the same element multiple times. Using @FindBy, I have identified a web element and defined a WebElementFacacde for the same which is reusable.
Step 9 – Create the Step Definition class or Glue Code
A Step Definition is a Java method with an expression that links it to one or more Gherkin steps. When Cucumber executes a Gherkin step in a scenario, it will look for a matching step definition to execute. You can have all of your step definitions in one file, or in multiple files.
LoginPageDefinitions
package org.example.definitions;
import io.cucumber.java.en.Given;
import io.cucumber.java.en.Then;
import io.cucumber.java.en.When;
import net.serenitybdd.annotations.Steps;
import org.example.steps.StepHomePage;
import org.example.steps.StepLoginPage;
import static org.junit.jupiter.api.Assertions.*;
public class LoginPageDefinitions {
@Steps
StepLoginPage loginPage;
@Steps
StepHomePage homePage;
@Given("User is on Home page")
public void openApplication() {
loginPage.open();
}
@When("User enters username as {string}")
public void enterUsername(String userName) {
loginPage.inputUserName(userName);
}
@When("User enters password as {string}")
public void enterPassword(String passWord) {
loginPage.inputPassword(passWord);
loginPage.clickLogin();
}
@Then("User should be able to login successfully")
public void clickOnLoginButton() {
assertTrue(homePage.getHomPageTitle().contains("Dashboard"));
}
@Then("User should be able to see error message {string}")
public void unsuccessfulLogin(String expectedErrorMessage) {
String actualErrorMessage = loginPage.errorMessage();
assertEquals(expectedErrorMessage, actualErrorMessage);
}
@Then("User should be able to see error message {string} below username")
public void missingUsername (String expectedErrorMessage) {
String actualErrorMessage = loginPage.missingUsernameErrorMessage();
assertEquals(expectedErrorMessage, actualErrorMessage);
}
}
Assertions in JUnit-Jupiter are imported from the below package:-
import static org.junit.jupiter.api.Assertions.*;
Step 10 – Create a Serenity-Cucumber Runner class
Cucumber runs the feature files via JUnit and needs a dedicated test runner class to actually run the feature files.
import static io.cucumber.junit.platform.engine.Constants.GLUE_PROPERTY_NAME;
import org.junit.platform.suite.api.ConfigurationParameter;
import org.junit.platform.suite.api.IncludeEngines;
import org.junit.platform.suite.api.SelectClasspathResource;
import org.junit.platform.suite.api.Suite;
@Suite
@IncludeEngines("cucumber")
@SelectClasspathResource("org.example")
@SelectClasspathResource("/features")
@ConfigurationParameter(key = GLUE_PROPERTY_NAME, value = "org.example")
public class CucumberTestSuite {
}
Step 11 – Create cucumber.properties file under src/test/resources (optional)
This is an optional step. Cucumber of version 6.7 and above provides the functionality to generate a beautiful cucumber report. For this, it is needed to add a file cucumber.properties under src/test/resources.
cucumber.publish.enabled = true
Step 12 – Create junit-platform.properties in src/test/resources
Step 13 – Create serenity.conf file under src/test/resources
The serenity configuration file is used to configure the drivers so the test cases can run successfully. This file contains an operating system-specific binary. The binary file sits between your test and the browser. It acts as an intermediary, an interface between your tests and the browser you are using.
You can also configure the webdriver.base.url property for different environments in the serenity.conf configuration file.
webdriver {
driver = chrome
}
serenity.browser.maximized = true
#
# Define drivers for different platforms. Serenity will automatically pick the correct driver for the current platform
#
environments {
default {
webdriver.base.url = "https://opensource-demo.orangehrmlive.com/"
}
dev {
webdriver.base.url = "https://opensource-demo.orangehrmlive.com/dev"
}
staging {
webdriver.base.url = "https://opensource-demo.orangehrmlive.com/staging"
}
prod {
webdriver.base.url = "https://opensource-demo.orangehrmlive.com/prod"
}
}
Step 14 – Create serenity.properties file at the root of the project
serenity.project.name = Parallel Execution of Cucumber Scenarios with Serenity
Step 15 – Run the tests from Command Line
Open the command line and go to the location wherethe pom.xml of the project is present and type the below command.
mvn clean verify
Below is the test result of the test execution.
Step 16 – Run the tests from CucumberRunner
Right-click on the Ruuner class (CucumberTestSuite) and select Run ‘CucumberTestSuite’. (This is an image of IntelliJ Runner class).
The below image shows that 3 browsers open simultaneously.
Below is the test result of the test execution.
Step 17 – Serenity Report Generation
The best part about Serenity is the report generation by it. The Reports contain all possible types of information, you can think of with minimal extra effort. There is multiple types of reports are generated. We are interested in index.html and serenity-summary.html. To know more about Serenity Reports, please refer to tutorials for Index.html and Serenity-Summary.html. Below is the new Serenity Report.
Index.html
serenity-summary.html
If you want to control the number of browsers open in the test, then add the below-mentioned parameters in the junit-platform.properties:
Here, count=3 is the number of browsers that will open.
Please also remove <useUnlimitedThreads>true</useUnlimitedThreads> from pom.xml.
Note: While .fixed.max-pool-size effectively limits the maximum number of concurrent threads, Cucumber does not guarantee that the number of concurrently executing scenarios will not exceed this. This is from JUnit-Platform documentation.
We are done! Congratulations on making it through this tutorial and hope you found it useful! Happy Learning!!
In order to eliminate unreadable characters from the console output during execution, we set the monochrome option to true inside the @CucucmberOptions annotation. You can set this option to true or false. By default, it is set to False.
Monochrome as False in Cucumber
Monochrome is mentioned in the Runner class.
import io.cucumber.testng.AbstractTestNGCucumberTests;
import io.cucumber.testng.CucumberOptions;
@CucumberOptions(tags = "", features = "src/test/resources/Features", glue = "org.example.stepdefinitions", monochrome=false
,plugin = {"pretty"})
public class CucumberRunnerTests extends AbstractTestNGCucumberTests {
}
The output of the above program is
Monochrome as True in Cucumber
When monochrome value set to true, It will make console output for the Cucumber test much more readable and remove any unreadable character.
package org.example.runner;
import io.cucumber.testng.AbstractTestNGCucumberTests;
import io.cucumber.testng.CucumberOptions;
@CucumberOptions(tags = "", features = "src/test/resources/Features", glue = "org.example.stepdefinitions", monochrome=true
,plugin = {"pretty"})
public class CucumberRunnerTests extends AbstractTestNGCucumberTests {
}
The output of the above program is
Congratulations on making it through this tutorial and hope you found it useful! Happy Learning!! Cheers!!
Assertions in TestNG are a way to verify that the expected result and the actual result match not in the test case. A test is considered successful ONLY if it is completed without throwing any exceptions. An example of assertion can be logging into the website, checking the title of the webpage, verifying the functionality of an input box that takes only integers, etc.
If the project is a Maven project, then please add the latest TestNG dependency in the pom.xml.
Hard Assertion throws AssertionError immediately when an Assert Condition fails and moves to the next @Test method
Suppose, there are 2 assertions in a Test and the first assertion fails, then HardAssertion does not execute the second Assertion Condition and declares the test as failed
As you can see in the below example, there are 2 assert conditions under Test – AssertionFailure(). As the first Assert Condition fails, it moved directly to the second test without executing another Assert Condition.
package org.example;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.firefox.FirefoxDriver;
import org.openqa.selenium.firefox.FirefoxOptions;
import org.testng.Assert;
import org.testng.annotations.Test;
public class HardAssertionDemo {
@Test
public void AssertionFailure() {
FirefoxOptions firefoxOptions = new FirefoxOptions();
WebDriver driver = new FirefoxDriver(firefoxOptions);
driver.get("https://duckduckgo.com/");
String expectedTitle = "DuckDuckGo";
String actualTitle = driver.getTitle();
String actualText1 = driver.findElement(By.xpath("//*[@class='homepage-cta-section_title__Lovig heading_heading2__oEFPn heading_heading__IiMSV']")).getText();
/* Hard Assert */
System.out.println("Verify Title :" + actualTitle);
Assert.assertEquals(actualTitle, expectedTitle, "Incorrect page title");
System.out.println("Verify Text :" + actualText1);
Assert.assertEquals(actualText1, "Privacy Protection For Any Device");
driver.quit();
}
@Test
public void print() {
System.out.println("Hard Assertion is displayed");
}
}
The output of the above program is
What is Soft Assert?
To overcome the above-mentioned problem, there is another type of assertion called Soft Assert.
Soft Assert does not throw an exception when an Assert Condition fails, and continues with the next step after the Assert Condition.
Soft assert does not include by default in TestNG. For this, you need to include the below package :
org.testng.asserts.SoftAssert;
The first step is to create an instance of SoftAssert class.
SoftAssert softAssertion = new SoftAssert();
After this, we can use this softAssert variable instead of hard assert.
Create an object of SoftAssertion to run Assert Conditions
Below is an example of a Soft Assert.
package org.example;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.firefox.FirefoxDriver;
import org.openqa.selenium.firefox.FirefoxOptions;
import org.testng.annotations.Test;
import org.testng.asserts.SoftAssert;
public class SoftAssertionDemo {
@Test
public void assertionFailure() {
SoftAssert softAssertion = new SoftAssert();
FirefoxOptions firefoxOptions = new FirefoxOptions();
WebDriver driver = new FirefoxDriver(firefoxOptions);
driver.manage().window().maximize();
driver.get("https://duckduckgo.com/");
String expectedTitle = "DuckDuckGo";
String actualTitle = driver.getTitle();
String actualText1 = driver.findElement(By.xpath("//*[@class='homepage-cta-section_title__Lovig heading_heading2__oEFPn heading_heading__IiMSV']")).getText();
/* Soft Assert */
System.out.println("Verify Title :" + actualTitle);
softAssertion.assertEquals(actualTitle, expectedTitle, "Incorrect page title");
System.out.println("Verify Text :" + actualText1);
softAssertion.assertEquals(actualText1, "Privacy Protection For Any Device");
driver.quit();
}
@Test
public void print() {
System.out.println("Soft Assertion is displayed");
}
}
The output of the above program is
AssertAll
If there is any exception, and you want to throw it, then you need to use assertAll() method as a last statement in the @Test and test suite again to continue with the next @Test as it is.
package org.example;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.firefox.FirefoxDriver;
import org.openqa.selenium.firefox.FirefoxOptions;
import org.testng.annotations.Test;
import org.testng.asserts.SoftAssert;
public class AssertAllDemo {
@Test
public void assertionFailure() {
SoftAssert softAssertion = new SoftAssert();
FirefoxOptions firefoxOptions = new FirefoxOptions();
WebDriver driver = new FirefoxDriver(firefoxOptions);
driver.manage().window().maximize();
driver.get("https://duckduckgo.com/");
String expectedTitle = "DuckDuckGo";
String actualTitle = driver.getTitle();
String actualText1 = driver.findElement(By.xpath("//*[@class='homepage-cta-section_title__Lovig heading_heading2__oEFPn heading_heading__IiMSV']")).getText();
/* AssertAll */
System.out.println("Verify Title :" + actualTitle);
softAssertion.assertEquals(actualTitle, expectedTitle, "Incorrect page title");
System.out.println("Verify Text :" + actualText1);
softAssertion.assertEquals(actualText1, "Privacy Protection For Any Device");
softAssertion.assertAll();
driver.quit();
}
@Test
public void print() {
System.out.println("Soft Assertion is displayed");
}
}
The output of the above program is
In the above program, we can see that both assertions of Test – assertionFailure are executed, but as the first assertion has failed, the test – assertionFailure is marked as failed.
Congratulations on making it through this tutorial and hope you found it useful! Happy Learning!! Cheers!!
GitLab is the open DevOps platform, delivered as a single application. This makes GitLab unique and creates a streamlined software workflow, unlocking your organization from the constraints of a pieced-together toolchain. Learn how GitLab offers unmatched visibility and higher levels of efficiency in a single application across the DevOps lifecycle.
Google has developed a JSON library for Java called Gson. We can create JSON and translate it into Java objects using Gson. Gson can output JSON in compact format by default. The setPrettyPrinting() function of the GsonBuilder class must be used to set up the Gson instance in order to enable pretty printing. This method tells Gson to produce JSON that fits on a page for pretty printing.
Add the below dependency to POM.xml to use Gson API.
Let us create a table named Employee which contains the data members same as node names in the above JSON payload and their corresponding getter and setter methods.
public class Employee {
// private data members of POJO class
private String firstName;
private String lastName;
private int age;
private double salary;
private String designation;
private String contactNumber;
private String emailId;
// Getter and setter methods
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public double getSalary() {
return salary;
}
public void setSalary(double salary) {
this.salary = salary;
}
public String getDesignation() {
return designation;
}
public void setDesignation(String designation) {
this.designation = designation;
}
public String getContactNumber() {
return contactNumber;
}
public void setContactNumber(String contactNumber) {
this.contactNumber = contactNumber;
}
public String getEmailId() {
return emailId;
}
public void setEmailId(String emailId) {
this.emailId = emailId;
}
}
We will convert a Java Object to a JSON object as a String and also will write it into a .json file. There are many variations for the method toJson().
You can create a Gson instance by invoking a new Gson() if the default configuration is all you need, as shown in the below example.
@Test
public void withoutPretty() {
// Create an object of POJO class
Employee employee = new Employee();
employee.setFirstName("Vibha");
employee.setLastName("Singh");
employee.setAge(30);
employee.setSalary(75000);
employee.setDesignation("Manager");
employee.setContactNumber("+919999988822");
employee.setEmailId("abc@test.com");
Gson gson = new Gson();
String employeeJsonPayload = gson.toJson(employee);
System.out.println("Json :" + employeeJsonPayload);
}
The execution message is shown below.
Syntax
public GsonBuilder setPrettyPrinting()
Below is the program to print the JSON in pretty format.
@Test
public void withPretty() {
// Create an object of POJO class
Employee employee = new Employee();
employee.setFirstName("Vibha");
employee.setLastName("Singh");
employee.setAge(30);
employee.setSalary(75000);
employee.setDesignation("Manager");
employee.setContactNumber("+919999988822");
employee.setEmailId("abc@test.com");
Gson gson = new GsonBuilder().setPrettyPrinting().create();
String json = gson.toJson(employee);
System.out.println("Pretty Json :" + json);
}
The output of the above program is
We are done! Congratulations on making it through this tutorial and hope you found it useful! Happy Learning!!
Serenity BDD is an open-source library that aims to make the idea of living documentation a reality. Serenity BDD helps you write cleaner and more maintainable automated acceptance and regression tests faster. Serenity also uses the test results to produce illustrated, narrative reports that document and describe what your application does and how it works. Serenity tells you not only what tests have been executed, but more importantly, what requirements have been tested
Let us create a table named Employee which contains the data members same as node names in the above JSON payload with @Expose annotation and their corresponding getter and setter methods.
package com.example.gson;
import com.google.gson.annotations.Expose;
import java.math.BigDecimal;
import java.util.List;
import java.util.Map;
public class Employee {
// private data members of POJO class
@Expose(serialize = true)
private String firstName;
@Expose(serialize = true)
private String lastName;
@Expose(serialize = false)
private int age;
@Expose(serialize = true)
private Map<String, BigDecimal> salary;
@Expose()
private String designation;
@Expose(serialize = false)
private String contactNumber;
@Expose(serialize = true)
private List<String> emailId;
// Getter and setter methods
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public Map<String, BigDecimal> getSalary() {
return salary;
}
public void setSalary(Map<String, BigDecimal> salary) {
this.salary = salary;
}
public String getDesignation() {
return designation;
}
public void setDesignation(String designation) {
this.designation = designation;
}
public String getContactNumber() {
return contactNumber;
}
public void setContactNumber(String contactNumber) {
this.contactNumber = contactNumber;
}
public List<String> getEmailId() {
return emailId;
}
public void setEmailId(List<String> emailId) {
this.emailId = emailId;
}
@Override
public String toString() {
return "(firstName: " + firstName + "," +
"lastName: " + lastName + "," +
"age: " + age + ", " +
"salary: " + salary + "," +
"designation: " + designation + ", " +
"contactNumber: " + contactNumber + ", " +
"emailId: " + emailId + ")";
}
}
Suppose the attribute age and contactNumber in the Employee class should not serialize because it’s sensitive information. Hence, we must decorate these attributes with the annotation @Expose(serialize=false):
To use @Expose annotation, we must create a Gson instance by using the GsonBuilder class and its excludeFieldsWithoutExposeAnnotation() method.
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import org.junit.Test;
import java.math.BigDecimal;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
public class GsonExpose_Demo {
@Test
public void gsonExposeTest() {
// Create an object of POJO class
Employee employee = new Employee();
employee.setFirstName("Vibha");
employee.setLastName("Singh");
employee.setAge(30);
Map<String, BigDecimal> salary = new HashMap() {{
put("2010", new BigDecimal(10000));
put("2012", new BigDecimal(12000));
put("2018", new BigDecimal(14000));
}};
employee.setSalary(salary);
employee.setDesignation("Manager");
employee.setContactNumber("+919999988822");
employee.setEmailId(Arrays.asList("abc@test.com","vibha@test.com"));
Gson gson = new GsonBuilder().setPrettyPrinting().excludeFieldsWithoutExposeAnnotation().create();
String employeeJsonPayload = gson.toJson(employee);
System.out.println("Json :" + employeeJsonPayload);
}
}
The output of the above program is shown below.
We can see here that age and contactNumber are not shown in the JSON body.
We are done! Congratulations on making it through this tutorial and hope you found it useful! Happy Learning!!