API is the acronym for Application Programming Interface, which acts as an interface between two applications to communicate with each other irrespective of the programming languages used to develop them. API testing plays a crucial role in the software development process as it helps us to test the business logic of the application even before the UI is ready. There are different types of APIs such as SOAP, REST, and RPC, etc. For now, we will focus on REST API testing using REST Assured.
- What is REST ASSURED and How it works
REST stands for REpresentational State Transfer. REST Assured is a java library used for testing and validating the Restful Web Services. It supports Behavior-Driven Development(BDD) syntax like Given, When, and Then notations. It helps us to integrate with testing frameworks like Junit or TestNG.
Let us understand how the Rest Assured Works
- Create an HTTP request with all the details
- Send the request over the network
- Validate the received Response
2. HTTP Request
An HTTP request consists of the following
2.1 URL
The Request URL is the unique address used to make a request. URL consists of the Base URL, Resource, Query, or Path Parameters.
Example: https://reqres.in/api/users/2
Base URL
It is the Base Address for the particular API.
Resource:
A Resource represents the collection that can be accessed from the server.
Path Parameter:
The Path parameter is the variable part of a URL. It is used to point to a particular resource within a collection, such as a user with a specific ID. In Path Parameter we move to the subresource.
Query Parameter:
Query Parameters are optional parameters. It is used to sort/filter the resource. For appending query parameter ‘?’ is added to the end of the URL and implemented as a key-value pair. For Appending multiple query parameters ‘&’ is used in between the key-value pairs.
2.2 HTTP Method/Verb
The four basic Create, Read, Update and Delete (CRUD) operations are performed using the POST, GET, PUT and DELETE methods in the REST interface
POST: This Verb is used to create a new resource on a server.
GET: This Verb is used to get or read data from a server.
PUT or PATCH: Both PUT and PATCH Verbs are used to update a resource on a server. The PUT method is used to update the record entirely. The PATCH method is used to update the record partially instead of updating the entire resource.
DELETE: This Verb is used to delete a resource from a server.
2.3 Headers
Headers represent the meta-data associated with HTTP requests or responses. It is the additional information that is passed between client and server along with the request or response. Headers are used for several purposes, such as authentication, caching, messaging body information, handling cookies, etc. Headers will be key-value pairs or can be a key with multiple values.
2.4 Payload/Body
The Payload/Body contains the information that the user wants to send to the server. The payload is used only with the requests that alter the existing resource or create new ones.
3. HTTP Response
The HTTP Response consists of the status code, Headers and Response body
As we already discussed Headers and Body we will focus on Status Codes
3.1 Status Codes
HTTP status codes help us to understand the status of the response quickly.
100–199: Informational: The request received and process continuing
200–299: Success: The request succeeded
300–399: Redirection: The request is redirecting to another URL
400–499: Client Error: An error occurred from client-side
500–599: Server Error: An error occurred from the server-side
4. Creating a REST Assured Project
- Create a Maven Project in the Eclipse/IntelliJ
File->New-> Project -> Maven -> Maven Project -> Create a simple Project -> Next -> Enter Group id ->Artifact id-> Finish
Update your pom.xml with below dependencies and build information
================================================================
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>RestAssuredAPIAutomationMay62022</groupId>
<artifactId>RestAssuredAPIAutomationMay62022</artifactId>
<version>0.0.1-SNAPSHOT</version>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.1</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.19.1</version>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-source-plugin</artifactId>
<executions>
<execution>
<id>attach-sources</id>
<goals>
<goal>jar</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
<dependencies>
<!-- https://mvnrepository.com/artifact/io.rest-assured/rest-assured -->
<dependency>
<groupId>io.rest-assured</groupId>
<artifactId>rest-assured</artifactId>
<version>5.0.1</version>
<scope>test</scope>
</dependency>
<!-- https://mvnrepository.com/artifact/io.rest-assured/json-path -->
<dependency>
<groupId>io.rest-assured</groupId>
<artifactId>json-path</artifactId>
<version>5.0.1</version>
<scope>test</scope>
</dependency>
<!-- https://mvnrepository.com/artifact/io.rest-assured/json-schema-validator -->
<dependency>
<groupId>io.rest-assured</groupId>
<artifactId>json-schema-validator</artifactId>
<version>5.0.1</version>
</dependency>
<!-- https://mvnrepository.com/artifact/io.rest-assured/xml-path -->
<dependency>
<groupId>io.rest-assured</groupId>
<artifactId>xml-path</artifactId>
<version>5.0.1</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.junit.jupiter/junit-jupiter-api -->
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-api</artifactId>
<version>5.7.2</version>
<scope>test</scope>
</dependency>
<!-- https://mvnrepository.com/artifact/org.hamcrest/java-hamcrest -->
<dependency>
<groupId>org.hamcrest</groupId>
<artifactId>java-hamcrest</artifactId>
<version>2.0.0.0</version>
<scope>test</scope>
</dependency>
<!-- https://mvnrepository.com/artifact/org.hamcrest/hamcrest-all -->
<dependency>
<groupId>org.hamcrest</groupId>
<artifactId>hamcrest-all</artifactId>
<version>1.3</version>
<scope>test</scope>
</dependency>
<!-- https://mvnrepository.com/artifact/org.json/json -->
<dependency>
<groupId>org.json</groupId>
<artifactId>json</artifactId>
<version>20220320</version>
</dependency>
<!-- https://mvnrepository.com/artifact/io.cucumber/cucumber-java -->
<dependency>
<groupId>io.cucumber</groupId>
<artifactId>cucumber-java</artifactId>
<version>7.3.4</version>
</dependency>
<!-- https://mvnrepository.com/artifact/io.cucumber/cucumber-junit -->
<dependency>
<groupId>io.cucumber</groupId>
<artifactId>cucumber-junit</artifactId>
<version>7.3.4</version>
<scope>test</scope>
</dependency>
<!-- https://mvnrepository.com/artifact/io.cucumber/cucumber-core -->
<dependency>
<groupId>io.cucumber</groupId>
<artifactId>cucumber-core</artifactId>
<version>7.3.4</version>
</dependency>
<!-- https://mvnrepository.com/artifact/net.masterthought/cucumber-reporting -->
<dependency>
<groupId>net.masterthought</groupId>
<artifactId>cucumber-reporting</artifactId>
<version>5.7.0</version>
</dependency>
</dependencies>
</project>
===========================================================
4.1 Automate HTTP Request
We know that REST Assured supports BDD format i.e given, when and then statements
- given() — We provide all the input details here i.e. Base URI, Headers, Path Parameter, Query Parameter, and Request Body/Payload.
- when() — We specify the Resource, HTTP Request method like POST, GET, PUT, PATCH, or DELETE.
- then() — We validate the response i.e the response code, response time, response message, response headers, response body, etc.
Create a folder structure like below screen
under src/test/main
1)com.qa.api.rest.base
create TestBase.java class
2)com.qa.api.rest.config
create config.properties file
3)create Features folder
4)create step_def package
5)create testRunner package
Create Step_def file for above feature steps
package step_def;
import java.util.List;
import org.junit.jupiter.api.Assertions;
import com.qa.api.rest.base.TestBase;
import io.cucumber.datatable.DataTable;
import io.cucumber.java.en.Given;
import io.cucumber.java.en.Then;
import io.cucumber.java.en.When;
import io.restassured.RestAssured;
import io.restassured.response.Response;
public class GetAPITest extends TestBase{
Response resp;
@Given("^provide valid endpoint to fetch all users$")
public void provide_valid_endpoint_to_fetch_all_users() throws Throwable {
//setting the base Url
RestAssured.baseURI=readPropertyValue("baseUrl");
//setting the endpoint url
RestAssured.basePath=readPropertyValue("getAllUserEndPoint");
}
@When("^the request is send to the server$")
public void the_request_is_send_to_the_server() throws Throwable {
resp=RestAssured.given().header("Accept","application/json").
header("Content-type", "application/json").
queryParam("page", 2).
when().
get().
then().
contentType("application/json").
extract().response();
}
@Then("^validate the response statuscode 200$")
public void validate_the_response_statuscode_200() throws Throwable {
int respCode=resp.getStatusCode();
Assertions.assertEquals(respCode, 200);
}
@When("^the request is send to the server with page number as \"([^\"]*)\"$")
public void the_request_is_send_to_the_server_with_page_number_as_something(int pageNumber) throws Throwable {
resp=RestAssured.given().header("Accept","application/json").
header("Content-type", "application/json").
queryParam("page", pageNumber).
when().
get().
then().
contentType("application/json").
extract().response();
}
@Then("^validate the response of first user record having email as \"([^\"]*)\"$")
public void validate_the_response_of_first_user_record_having_email_as_something(String emailid) throws Throwable {
//extracting the response body field value
String email=resp.path("data[0].email");
Assertions.assertEquals(email, emailid);
}
@Then("^validate response statuscode (.+)$")
public void validate_response_statuscode(int respstatuscode) throws Throwable {
int respCode=resp.getStatusCode();
Assertions.assertEquals(respCode, respstatuscode);
}
@Given("^provide valid endpoint to fetch the single user$")
public void provide_valid_endpoint_to_fetch_the_single_user() throws Throwable {
//set the base url
RestAssured.baseURI=readPropertyValue("baseUrl");
//set the basepath
RestAssured.basePath=readPropertyValue("getSingleUserEndPoint");
}
@When("^the request is send to the server to fetch single user$")
public void the_request_is_send_to_the_server_to_fetch_single_user() throws Throwable {
resp=RestAssured.given().header("Accept","application/json").
header("Content-type", "application/json").
when().
get("/2").
then().
contentType("application/json").
extract().response();
}
@Then("^validate the response body fields$")
public void validate_the_response_body_fields(DataTable values) throws Throwable {
List<List<String>>ls=values.asLists();
int id=resp.path("data.id");
System.out.println("id value is:"+id);
Assertions.assertEquals(Integer.parseInt(ls.get(0).get(0)), id);
//fetch the email
String emailVal=resp.path("data.email");
System.out.println("email value is:"+emailVal);
Assertions.assertEquals(ls.get(0).get(1), emailVal);
//fetch the first name
String firstNameVal=resp.path("data.first_name");
System.out.println("firstName value is:"+firstNameVal);
Assertions.assertEquals(ls.get(0).get(2), firstNameVal);
//fetch the lastname
String lastnameVal=resp.path("data.last_name");
System.out.println("lastname value is:"+lastnameVal);
Assertions.assertEquals(ls.get(0).get(3), lastnameVal);
}
@Given("^provide valid endpoint to fetch the single userNotFound$")
public void provide_valid_endpoint_to_fetch_the_single_usernotfound() throws Throwable {
//set the base url
RestAssured.baseURI=readPropertyValue("baseUrl");
//set the basepath
RestAssured.basePath=readPropertyValue("getSingleUserNotFoundEndPoint");
}
@When("^the request is send to the server to fetch single user not found$")
public void the_request_is_send_to_the_server_to_fetch_single_user_not_found() throws Throwable {
resp=RestAssured.given().header("Accept","application/json").
header("Content-type", "application/json").
when().
get().
then().
contentType("application/json").
extract().response();
}
@Then("^validate the response statuscode$")
public void validate_the_response_statuscode(DataTable exrespcode) throws Throwable {
int respCode=resp.getStatusCode();
List<String>ls=exrespcode.asList();
int expval=Integer.parseInt(ls.get(0));
Assertions.assertEquals(respCode,expval);
}
}
=========================================
Create a Runner file
============================================
package testRunner;
import org.junit.runner.RunWith;
import io.cucumber.junit.Cucumber;
import io.cucumber.junit.CucumberOptions;
@RunWith(Cucumber.class)
@CucumberOptions(
features = "D:\\eclipseworkspaceAug2018\\RestAssuredAPIAutomationMay62022\\src\\test\\java\\Features",
glue = {"step_def"},
plugin={"pretty","html:target/report.html", "json:json_output/cucumber.json", "junit:junit_xml/cucumber.xml"},
dryRun=false, //mapping between feature & stepdefinition is proper or not
monochrome=true,//display the console output in a proper readable format
publish = true,
stepNotifications=true
//tags = "@smoke"
)
public class TestRunner {
}