Gson is a Java library that can be used to convert Java Objects into their JSON representation. It can also be used to convert a JSON string to an equivalent Java object. Gson can work with arbitrary Java objects, including pre-existing objects those you do not have source code.
Provide simple toJson() and fromJson() methods to convert Java objects to JSON and vice-versa.
Allow pre-existing unmodifiable objects to be converted to and from JSON.
Extensive support of Java Generics.
Allow custom representations for objects.
Support arbitrarily complex objects (with deep inheritance hierarchies and extensive use of generic types).
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.
You can also use GsonBuilder to build a Gson instance with various configuration options such as versioning support, pretty-printing, custom JsonSerializer, JsonDeserializer.
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import org.junit.Test;
public class EmployeeGsonTest {
@Test
public void gsonSerializationTest() {
// 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);
Gson builder = new GsonBuilder().setPrettyPrinting().create();
String employeePrettyJsonPayload = builder.toJson(employee);
System.out.println("Pretty Json :" + employeePrettyJsonPayload);
}
}
The execution message is shown below.
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.
What is SpringBoot Application?
Spring Boot is an open-source micro framework that provides Java developers with a platform to get started with an auto-configurable production-grade Spring application.
Comes with embedded HTTP servers like Tomcat orJetty to test web applications.
Adds many plugins that developers can use to work with embedded and in-memory databases easily. Spring allows you to easily connect with database and queue services like Oracle, PostgreSQL, MySQL, MongoDB, Redis, Solr, ElasticSearch, Rabbit MQ, and others.
Prerequisite
Serenity seamlessly supports Cucumber 6 and Cucumber 7. However, this flexibility requires a little tweaking in the build dependencies. For the Maven project, you need to do the following:
Add serenity-cucumber dependency
Add Springboottest dependency to start up an application context to be used in a test.
Add Junit-Vintage dependency as it is needed for spring boot application of version 2.4 and above with JUnit4.
Project Directory Structure
Relationship between SpringBoot, Serenity BDD, Cucumber and Rest Assured
Implementation Steps
Create a source folder – src/test/resources to create test scenarios in the Feature file
AddSpringBoot, Serenity, Cucumber,and JUnit4 dependencies to the project
Create a feature file under src/test/resources
Create the StepDefinition and Helper classes.
Create a Serenity Runner class in the src/test/java directory
Run the tests from JUnit
Run the tests from Command Line
Serenity Report Generation
CucumberReport Generation
Step 1 – Create a source folder – src/test/resources
Right-click on the test directory and select New->Directory and select resources (Maven Source Directories). Create a source folder – src/test/resources to create test scenarios in the Feature file
Step 2 – Add SpringBoot, Serenity, Cucumber, and JUnit4 dependencies to the project
We have added SpringBootTest, Serenity, Cucumber, JUnit4, and JUnit Vintage.
Step 3 – Create a feature file under src/test/resources
Below is an example of a feature file which shows a sample test scenario.
Feature: SpringBoot Request
@ReceiveCorrectResponse
Scenario Outline: Send a valid Request to get correct response
Given I send a request to the URL "<url>"
Then the response will return "<response>"
Examples:
| url | response |
| / | Hello World, Spring Boot! |
| /qaautomation | Hello QA Automation! |
The test class mentioned below (AbstractRestAssuredHelper) contains integration tests for the spring boot rest controller mentioned. This test class:
uses @SpringBootTest annotation which loads the actual application context.
uses WebEnvironment.RANDOM_PORT to create and run the application at some random server port.
@LocalServerPort gets the reference of the port where the server has started. It helps in building the actual request URIs to mimic real client interactions.
Step 4 – Create the StepDefinition and Helper classes
Below is the code of the StepDefinition and Helper class. These classes are created in the src/test/java directory.
This class sends the request and receives a response after performing the GET operation. Here, the validation of the response also takes place by asserting the expected and actual response
To use Rest-assured, Serenity provides the class SerenityRest
import org.junit.Assert;
import io.cucumber.java.en.Given;
import io.cucumber.java.en.Then;
import io.restassured.response.Response;
import net.serenitybdd.rest.SerenityRest;
import net.thucydides.core.annotations.Steps;
public class SpringBootDemoDefinitions {
@Steps
AbstractRestAssuredHelper helper;
private Response response;
@Given("I send a request to the URL {string}")
public void iSendARequest(String endpoint) throws Exception {
response = helper.getAnonymousRequest().contentType("application/json")
.header("Content-Type", "application/json").when().get(endpoint);
}
@Then("the response will return {string}")
public void extractResponse(String Expected ) {
SerenityRest.restAssuredThat(response -> response.statusCode(200));
String Actual = response.asString();
Assert.assertEquals(Expected, Actual);
}
}
Step 5 – Create a Serenity Runner class in the src/test/java directory
We cannot run a Feature file on its own in cucumber-based framework. We need to create a Java class that will run the Feature File. It is the starting point for JUnit to start executing the tests. TestRunner class is created under src/ test/java. When you run the tests with serenity, you use the CucumberWithSerenitytest runner. If the feature files are not in the same package as the test runner class, you also need to use the @CucumberOptionsclass to provide the root directory where the feature files can be found.
You can run the tests from SpringRunnerTests class. Right-click on the class and select Run ‘SpringRunnerTests’.
Step 7 – Run the tests from Command Line
Run the tests from the command line by using the below command
mvn clean verify
The output of the above program is
The test execution status is shown below:
Step 8 – Serenity Report Generation
By default, the test report generated by Serenity is placed under target/site/serenity/index.html. Below is the sample Serenity Report.
Go to the Test Results tab and we can see all the test scenarios.
Step 9 – CucumberReport Generation
Cucumber Report can be generated by adding publish=true in SpringRunnerTests as shown in the above example. Click on the link provided in the execution status.
Jenkin’s installed and started on the computer. The current Jenkins version is – 2.361.2
To generate HTML Report in Jenkins, we need to download HTML Publisher Plugin. Please refer to this tutorial to install the plugin – How to install Plugins in Jenkins.
Implementation Steps
Step 1: Create a new Maven project
Give the Name of the project – ExtentReport_Demo
Click on the Maven project.
Click on the OK button.
In the General section, enter the project description in the Description box.
Select Source Code Management as None if the project is locally present on the machine.
Step 2: Build Management
Go to the Build section of the new job.
In the Root POM textbox, enter the full path to pom.xml
In the Goals and options section, enter “clean test site”
Here, I have used the Selenium project with JUnit, so to see the complete project, please refer to this tutorial – How to generate JUnit4 Report.
Click on the Advanced button.
Step 3: Select a custom workspace
Mention the full path of the project in the directory.
Step 4: Select “Publish HTML reports” from “Post Build Actions”
Scroll down to “Post Build Actions” and click on the “Add Post Build Actions” drop-down list. Select “Publish HTML reports“.
If you want to see where the report is saved in Jenkins, go to the Dashboard ->ExtentReport_Demo project -> Workspace ->target -> Reports -> Spark.html.
Enter the HTML directory to archive – Reports, Index page[s] – Spark.html, and Report title – Extent Report.
Click on the Apply and Save buttons.
We have created a new Maven project “ExtentReport_Demo” with the configuration to run the Cucumber, and Selenium with TestNG Tests and also to generate HTML Report after execution using Jenkins.
Step 5: Execute the tests
Let’s execute it now by clicking on the “Build Now” button.
Right-click on Build Number (here in my case it is #4).
Click on Console Output to see the result.
Step 6: View the Extent Report
Once the execution is completed, click on go “Back to Project“, and we can see a link to view the “Extent Report“.
We can see here that the Extent Report link is displayed in the Console.
Below is the Extent Report generated in Jenkins.
Tip: If you don’t see the Report UI intact, then you need to configure a simple Groovy script. For that, go to Dashboard–>Manage Jenkins–>Script Console and add the script as:
4. To generate a JUnit Report in Jenkins, we need to download the JUnit Plugin. Please refer to this tutorial to install the plugin – How to install Plugins in Jenkins
Implementation Steps
Step 1: Start the Jenkins server
Start the Jenkins server open the browser and navigate to the below endpoint
In the General section, enter the project description in the Description box.
Select a custom workspace and provide the full path of the project.
Select Source Code Management as None if the project is locally present on the machine
Step 3: Build Steps
In the Build Steps section, select Invoke top-level Maven targets.
The Build Steps window will extend. Mention the below details:-
Maven Version – MAVEN_HOME
Goals – clean test
Click on the Advanced button.
Step 4: Provide the full path to pom.xml
Specify the full path to pom.xml in POM.
Step 5: Select “Publish JUnit test result report” from “Post Build Actions”
Scroll down to “Post Build Actions” and click on the “Add Post Build Actions” drop-down list. Select “Publish JUnit test result report“.
Enter the Result Path as “**/target/surefire-reports/*.xml”.
Click on the Applyand Save buttons.
We have created a new Maven project “JUnitReport_Demo” with the configuration to run the Selenium with JUnit Tests and also to generate JUnit Report after execution using Jenkins.
Step 6: Execute the tests
Let’s execute it now by clicking on the “Build Now” button.
Right-click on Build Number (here in my case it is #2).
Click on Console Output to see the result.
Step 7: View the JUnit Report
Once the execution is completed, we could see a link to view the “Test Report“.
Below is the summary of the Test Execution.
This way, we could generate JUnit Report using Jenkins.
Congratulations on making it through this tutorial and hope you found it useful! Happy Learning!! Cheers!!
The two most used classes for managing Excel Workbooks are:
HSSFWorkbook – These class methods are used to read/write data to Microsoft Excel file in .xls format. It is compatible with MS-Office versions 97–2003.
XSSFWorkbook – These class methods are used to read-write data to Microsoft Excel in .xls or .xlsx format. It is compatible with MS-Office versions 2007 or later.
How to read Excel (.xlsx) from specific cell value?
Step 1 – To locate the location of file.
File file = new File("C:\\Selenium_ReadTestData.xlsx");
Import File from package
import java.io.File;
Step 2– Instantiate FileInputStream to read from the file specified.
Here getRow(0) will look into the first row, and getCell(0) will look into the first column, i.e. A1.
To retrieve the String value we are making use of getStringCellValue in the end.
Below is the Excel which I’m using to read the data as mentioned below:-
We want to get the value of Row 1, Cell B
We want to get the value of Row 3, Cell A
Let us create a program for the same scenario:
import java.io.FileInputStream;
import java.io.IOException;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
public class ReadSpecificData {
public static void main(String[] args) {
String path = "C:\\Selenium_ReadTestData.xlsx";
try {
//Create an object of FileInputStream class to read excel file
FileInputStream fis = new FileInputStream(path);
//Create object of XSSFWorkbook class
XSSFWorkbook wb = new XSSFWorkbook(fis);
//Read excel sheet by sheet name
XSSFSheet sheet1 = wb.getSheet("Read_TestData");
//Get data from specified cell
System.out.println(sheet1.getRow(1).getCell(1).getStringCellValue());
System.out.println(sheet1.getRow(3).getCell(0).getStringCellValue());
} catch (IOException e) {
e.printStackTrace();
}
}
}
The output of the above program is
How to read the entire Excel sheet?
To read the complete data from Excel, you can iterate over each cell of the row, present in the sheet.
To get the last and first-row numbers, there are two methods in the sheet class:
getLastRowNum()
getFirstRowNum()
int rowCount=sheet.getLastRowNum()-sheet.getFirstRowNum();
Once you get the row, you can iterate over the cells present in the row by using the total number of cells, which we can calculate using getLastCellNum() method:
int cellcount=sheet.getRow(1).getLastCellNum();
Below is the entire program to read complete Excel.
import java.io.FileInputStream;
import java.io.IOException;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
public class ReadExcelFile {
public static void main(String args[]) throws IOException {
String path = "C:\\Selenium_ReadTestData.xlsx";
//Create an object of FileInputStream class to read excel file
FileInputStream fis = new FileInputStream(path);
//Create object of XSSFWorkbook class
Workbook workbook = new XSSFWorkbook(fis);
//Read excel sheet by sheet name
Sheet sheet = workbook.getSheet("Read_TestData");
//Find number of rows in excel file
int rowCount=sheet.getLastRowNum()-sheet.getFirstRowNum();
System.out.println("row count:"+rowCount);
//iterate over all the row to print the data present in each cell.
for(int i=0;i<=rowCount;i++){
//get cell count in a row
int cellcount=sheet.getRow(i).getLastCellNum();
//iterate over each cell to print its value
for(int j=0;j<cellcount;j++){
System.out.print(sheet.getRow(i).getCell(j).getStringCellValue().toString() +"||");
}
System.out.println();
}
}
}
The output of the above program is
That’s it! We are done.
Congratulations on making it through this tutorial and hope you found it useful! Happy Learning!! Cheers!!
The previous tutorial explained the Integration of Cucumber with Selenium and TestNG. Sometimes, inconsistent test results are common as a result of an unstable environment like network issue or Database down and soon. A few tests may fail for no obvious reason and then rerun successfully. We are sometimes required to run only failed test cases after bug fixes to verify fixes quickly. We will learn how to rerun failed test cases in the Cucumber with TestNG project in this post.
Cucumber provides a rerun plugin option in the Runner class. This option generates a file. The file contains information about the failed tests.
Now, let us add a rerun plugin to the Cucumber Runner class. Here, we are creating a failedrerun.txt file that contains the information about the failed test. This file will be created under the target folder.
import io.cucumber.testng.AbstractTestNGCucumberTests;
import io.cucumber.testng.CucumberOptions;
@CucumberOptions(tags = "", features = "src/test/resources/features/LoginPage.feature",
glue = "com.example.definitions",
plugin = {
"pretty",
"rerun:target/rerun.txt" // Saves paths of failed scenarios
}
)
public class RunnerTests extends AbstractTestNGCucumberTests {
}
Create a Second Runner Class
The next step is to run failed test scenarios existing in the text file. We need to create a class similar to our runner class. This class will contain the location of the file that we want to execute. It will rerun our failed scenarios. In the ‘features’ variable, you need to mention the failedrerun.txt file, and don’t forget that you must mention the ‘@’ symbol before the file path.
import io.cucumber.testng.AbstractTestNGCucumberTests;
import io.cucumber.testng.CucumberOptions;
@CucumberOptions(tags = "",
features = "@target/rerun.txt",
glue = "com.example.definitions",
plugin = {
"pretty"
}
)
public class RunnerTestsFailed extends AbstractTestNGCucumberTests {
}
Mention both Test Runner details in the 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.RunnerTests"/>
<class name="com.example.runner.RunnerTestsFailed"/>
</classes>
</test> <!-- Test -->
</suite> <!-- Suite -->
Run the tests using the below-mentioned command
mvn clean test
After running the tests from the command line, first, all the tests will be executed. If any test fails, a failedrerun.txt file will be generated that includes the details about the failed tests.
In the below screenshot, we can see that a scenario starting at line 25 has failed.
The first round of execution ends. Then, Cucumber Runner goes to the second runner. It runs the failed tests that are mentioned in failedrerun.txt.
We can see that 2 separate reports are generated here.
The first Cucumber Report shows that out of 5 tests, 1 test failed.
The second Cucumber Report shows that the one failed test is rerun again, and it again failed.
In the last tutorial, I explained How to test PUT Request using Rest Assured. In this tutorial, I will automate a DELETE Request using Rest Assured. I will verify the status code, line of Status, and content of the Response.
To set up a basic Rest Assured Maven Project, click here and Gradle project, click here.
Add the below-mentioned dependencies to the pom.xml.
An HTTP DELETE method is used to delete an existing resource from the collection of resources. The DELETE method requests the origin server to delete the resource identified by the Request-URI. On successful deletion of a resource, it returns 200 (OK) and 204 (No Content) status codes. It may return as 202 (Accepted) status code if the request is queued. To learn more about Rest API, please click here.
Below are the steps to test a DELETE Request using Rest Assured:
The steps to test the DELETE request are similar to any API request like GET, POST, or PUT. To know about the steps and various imports used in the below example in detail, please refer to the tutorial for POST Request.
Let’s see the existing details of an Employee ID 3 using Postman:
Let’s write DELETE request in REST Assured in Non BDD Format for id 3:-
import io.restassured.RestAssured;
import io.restassured.response.Response;
import io.restassured.response.ValidatableResponse;
import io.restassured.specification.RequestSpecification;
import org.junit.Test;
import static org.hamcrest.CoreMatchers.equalTo;
public class Delete_NonBddDemo {
RequestSpecification requestSpecification;
Response response;
ValidatableResponse validatableResponse;
@Test
public void deleteUser() {
RestAssured.baseURI = "https://dummy.restapiexample.com/api";
// Create a request specification
requestSpecification = RestAssured.given();
// Calling DELETE method
response = requestSpecification.delete("/v1/delete/3");
// Let's print response body.
String resString = response.prettyPrint();
/*
* To perform validation on response, we need to get ValidatableResponse type of
* response
*/
validatableResponse = response.then();
// Get status code
validatableResponse.statusCode(200);
// It will check if status line is as expected
validatableResponse.statusLine("HTTP/1.1 200 OK");
// Check response - message attribute
validatableResponse.body("message", equalTo("Successfully! Record has been deleted"));
}
}
The output of the above program is
Let’s write DELETE request in REST Assured in BDD Format:–
import io.restassured.http.ContentType;
import io.restassured.response.ValidatableResponse;
import org.junit.Test;
import static io.restassured.RestAssured.given;
import static org.hamcrest.CoreMatchers.equalTo;
public class Delete_BDDDemo {
ValidatableResponse validatableResponse;
@Test
public void deleteUser() {
validatableResponse = given()
.baseUri("https://dummy.restapiexample.com/api/v1/delete/3")
.contentType(ContentType.JSON)
.when()
.delete()
.then()
.assertThat().statusCode(200)
.body("message", equalTo("Successfully! Record has been deleted"));
System.out.println("Response :" + validatableResponse.extract().asPrettyString());
}
}
The output of the above program is
Explanation:
1. GIVEN: Specifies the initial conditions or setup for the test.
In this tutorial, I will test a SOAP Service using Rest Assured. I will verify the status code, line of Status, and content of the Response. To set up a basic Rest Assured Maven Project, click here and Gradle project, click here.
Add the below-mentioned dependencies to the pom.xml.
SOAP is an XML-based protocol for accessing web services over HTTP. It has some specifications that could be used across all applications.
SOAP messages are XML documents that are comprised of the following three basic building blocks:
The SOAP Envelope encapsulates all the data in a message and identifies the XML document as a SOAP message.
The Header element contains additional information about the SOAP message. This information could be authentication credentials, for example, which are used by the calling application.
The Body element includes the details of the actual message that needs to be sent from the web service to the calling application. This data includes call and response information.
Implementation Steps:
Step 1 – I have created an XML file for the soap request body in the project resource folder. “Number.xml” is the name of the file.
Step 2 – Specify the base URL to the RESTful web service using the RestAssuredclass.
RestAssured.baseURI = "http://www.dneonline.com";
Step 3 – The response to a request made by REST Assured.
Response response = given()
Response is imported from package:
import io.restassured.response.Response;
Step 4 – Set the content type to specify the format in which the request payload will be sent to the server. Here, the Content-Type is “text/xml; charset=utf-8”.
A Request Body is created by using the below snippet:
requestBody = new File(getClass().getClassLoader().getResource("Number.xml").getFile());
Step 6 – Send the POST request to the server and receive the response of the request made by REST Assured. This response contains every detail returned by hitting request i.e. response body, response headers, status code, status lines, cookies, etc. The response is imported from package:
import io.restassured.response.Response;
Step 7 – To validate a response like status code or value, we have used the below code
An assertion is a way to verify that the expected result and the actual result match or not in the test case. A test is considered successful ONLY if it is completed without throwing any exceptions. If the current value and the expected value match then the assertion passes and when the assertion passes nothing happens. But when an assertion fails, it will fail the test case.
There are various ways to perform assertions in API Testing. For API Testing, we are using Rest Assured, which uses either Hamcrest or JUnit assertions. We are going to discuss Hamcrest Assertions here.
What is Hamcrest?
Hamcrest is a framework for writing matcher objects, allowing ‘match’ rules to be defined declaratively. We do not need to add Hamcrest dependency explicitly as the Rest-Assured 4.3.3 version includes itself. To learn more about Hamcrest, please refer to this link.
We need to add the below dependency to use Hamcrest in the project. Please use the latest version from here
equalTo – It checks whether the extracted string from JSON is equal to the expected string.
equalToIgnoringCase – It checks if the extracted string from JSON matches the expected string. The comparison does not consider case (small or capital).
equalToIgnoringWhiteSpace – It checks if the extracted string from JSON matches the expected string. It takes into account the white spaces.
containsString– It checks whether the extracted string from JSON contains the expected string as a substring.
startsWith– It checks whether the extracted string from JSON is starting with a given string or character.
endsWith – It checks whether the extracted string from JSON is ending with a given string or character.
Below assertions are imported from the package shown below:-
Below are examples to show the use of collection-related assertions.
import io.restassured.RestAssured;
import io.restassured.http.ContentType;
import org.testng.annotations.Test;
import static org.hamcrest.Matchers.is;
import static org.hamcrest.Matchers.nullValue;
public class HamcrestNullAssertion {
public String endpoint = "https://restful-booker.herokuapp.com/booking/1";
@Test
public void nullAssertion() {
RestAssured.given().contentType(ContentType.JSON)
.when().get(endpoint)
.then().body("totalprice1", is(nullValue()));
}
}
The output of the above program is
hasKey
It checks whether the extracted map has an expected key.
import io.restassured.RestAssured;
import io.restassured.http.ContentType;
import org.testng.annotations.Test;
import static org.hamcrest.Matchers.hasKey;
public class HamcrestHasKeyAssertion {
public String endpoint = "https://restful-booker.herokuapp.com/booking/1";
@Test
public void collectionAssertions() {
RestAssured.given().contentType(ContentType.JSON)
.when().get(endpoint)
.then().body("bookingdates",hasKey("checkin"));
}
}
The output of the above program is
Not Assertion
The not assertion inverts the meaning of the other assertions. For example, if you want to perform negative assertions, then we can use any assertions with NOT.
The below assertion is imported from the package shown below:-
Below are examples to show the use of negative assertions.
import static org.hamcrest.Matchers.equalTo;
import static org.hamcrest.Matchers.not;
import io.restassured.RestAssured;
import io.restassured.http.ContentType;
import org.testng.annotations.Test;
public class HamcrestNotAssertion {
public String endpoint = "https://restful-booker.herokuapp.com/booking/1";
@Test
public void negativeAssertions() {
RestAssured.given().contentType(ContentType.JSON)
.when().get(endpoint)
.then().body("totalprice",not(equalTo(874)));
}
}
The output of the above program is
Multiple Assert Statements
In the below example, all 3 assertions will fail. It will only execute the first assertion. If the first assertion fails, then other assertions will not be executed.
import io.restassured.RestAssured;
import io.restassured.http.ContentType;
import org.testng.annotations.Test;
import static org.hamcrest.Matchers.equalTo;
public class HamcrestMultipleAssertions {
public String endpoint = "https://restful-booker.herokuapp.com/booking/1";
@Test
public void test1() {
RestAssured.given().contentType(ContentType.JSON)
.when().get(endpoint).then()
.body("firstname", equalTo("Jim"), // will fail
"lastname", equalTo("Smith"), // will fail
"totalprice", equalTo(314)); // will fail
}
}
The output of the above program is
To execute all the assertions in the test case, combine them into a single body. This should be done just like it is shown below. You can see that all the assertions failed, and they are shown in the response.
import io.restassured.RestAssured;
import io.restassured.http.ContentType;
import org.testng.annotations.Test;
import static org.hamcrest.Matchers.equalTo;
public class HamcrestMultipleAssertions {
public String endpoint = "https://restful-booker.herokuapp.com/booking/1";
@Test
public void test1() {
RestAssured.given().contentType(ContentType.JSON)
.when().get(endpoint).then()
.body("firstname", equalTo("Jim"), // will fail
"lastname", equalTo("Smith"), // will fail
"totalprice", equalTo(314)); // will fail
}
}
The output of the above program is
I have tried to show the use of a few of the most commonly used assertion methods. There are many more methods available in Hamcrest package. To know about other methods, write import static org.hamcrest.Matchers and add (.) at the end, it will show the list of all the methods available in Hamcrest.
To know more details related to Hamcrest assertion, you can refer the official website – Hamcrest
Points to Remember:
Hamcrest is commonly used in JUnit, RestAssured, and Mockito for API and unit testing
It offers a variety of matchers for different data types, such as: Numbers: greaterThan(), lessThan(), Strings: containsString(), startsWith(), endsWith()
You can combine multiple matchers using logical operators: assertThat(score, allOf(greaterThan(50), lessThan(100)))
Encourages fluent and expressive test writing with assertThat() instead of assertEquals()
We are done! Congratulations on making it through this tutorial and hope you found it useful! Happy Learning!!
JUnit 4 has a feature called parameterized tests. Parameterized test means to execute the test multiple times with different sets of test data. This eliminates the redundancy of the code. This helps the developers to save time by eliminating the need to copy the code multiple times. Parameterizing tests can increase code coverage and provide confidence that the code is working as expected. These are the steps that need to be followed to create a parameterized test.
Annotate test class with @RunWith(Parameterized.class).
Create an instance variable for each “column” of test data.
It has a single constructor that contains the test data.
Create a public static method annotated with @Parameters that returns a Collection of Objects (as Array) as test data set.
Create your test case(s) using the instance variables as the source of the test data.
The test case will be invoked once for each row of data.
There are multiple ways to parameterize a test. They are the following:
Parameterized Test with Constructor
Parameterized Test with Parameter Annotation
Parameterized Test using CSV File
Let us see parameterized tests in action.
1. Parameterized Test with Constructor
Steps to create a Parameterized JUnit test
1. Create a parameterized test class
Annotate your test class using @runWith(Parameterized.class).
Declaring the variable ‘num1’, ‘num2’, ‘num3’ as private and type as int.
@RunWith(value = Parameterized.class)
public class ParameterizedTest {
private int num1;
private int num2;
private int num3;
2. Create a constructor
Create a constructor that stores the test data. It stores 3 variables.
public ParameterizedTest(int num1, int num2, int num3) {
this.num1 = num1;
this.num2 = num2;
this.num3 = num3;
}
3. Create a static method that generates and returns test data.
Creating a two-dimensional array (providing input parameters for multiplication). Using the asList method, we convert the data into a List type. Since the return type of method input is the collection.
Using @Parameters annotation to create a set of input data to run our test.
The static method identified by @Parameters annotation returns a Collection, where each entry in the Collection will be the input data for one iteration of the test.
The complete code is shown below:
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import java.util.Arrays;
import java.util.Collection;
import static org.junit.Assert.assertEquals;
@RunWith(value = Parameterized.class)
public class ParameterizedTest {
private int num1;
private int num2;
private int num3;
public ParameterizedTest(int num1, int num2, int num3) {
this.num1 = num1;
this.num2 = num2;
this.num3 = num3;
}
@Parameterized.Parameters(name = "{index}: multiply({0}*{1}) = {2}")
public static Collection<Object[]> data() {
return Arrays.asList(new Object[][]{
{1, 1, 1},
{2, 2, 4},
{8, 2, 16},
{4, 5, 20},
{5, 5, 25}
});
}
@Test
public void multiplication() {
System.out.println("The product of "+num1+" and "+num2+" is "+num3);
assertEquals((num1*num2), num3);
}
}
The output of the above program is
2. Parameterized Test with Parameter Annotation
It is also possible to inject data values directly into fields without needing a constructor using the@Parameter annotation.
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import java.util.Arrays;
import java.util.Collection;
import static org.junit.Assert.assertEquals;
@RunWith(value = Parameterized.class)
public class ParameterizedTest1 {
@Parameterized.Parameter(value = 0)
public int num1;
@Parameterized.Parameter(value = 1)
public int num2;
@Parameterized.Parameter(value = 2)
public int num3;
@Parameterized.Parameters(name = "{index}: multiply({0}*{1}) = {2}")
public static Collection<Object[]> data() {
return Arrays.asList(new Object[][]{
{1, 1, 1},
{2, 2, 4},
{8, 2, 16},
{4, 5, 20},
{5, 5, 24}
});
}
@Test
public void multiplication() {
System.out.println("The product of "+num1+" and "+num2+" is "+num3);
assertEquals((num1*num2), num3);
}
}
The output of the above program is
3. Parameterized Test using CSV File
We can use an external CSV file to load the test data. This helps if the number of possible test cases is quite significant, or if test cases are frequently changed. The changes can be done without affecting the test code.
To start with, add a JUnitParams dependency to POM.xml
Let’s say that we have a CSV file with test parameters as JunitParamsTestParameters.csv:
Now let’s look at how this file can be used to load test parametersin the test method:
import junitparams.JUnitParamsRunner;
import org.junit.Test;
import org.junit.runner.RunWith;
import junitparams.FileParameters;
import static org.junit.Assert.assertEquals;
@RunWith(JUnitParamsRunner.class)
public class ParameterizedTest2 {
@Test
@FileParameters("src/test/resources/JunitParamsTestParameters.csv")
public void multiplication(int num1, int num2, int num3) {
System.out.println("The product of "+num1+" and "+num2+" is "+num3);
assertEquals((num1*num2), num3);
}
}
The output of the above program is
The parameterized test enables us to execute the same test over and over again using different values.
Important annotations to be used during parameterization
@RunWith
@Parameters
Congratulations. We are done. I hope this tutorial is helpful to you. Happy Learning!!