API Testing

Alphabin Technology Consulting
9 min readFeb 28, 2022

--

What is API Testing ?

API represents Application Programming Interface. It is the middle layer between UI and database. So once an API is built, it is necessary to test the interface. API testing is a kind of software testing that tests the API’s directly and validates the logic of architecture within a small amount of time. The fundamental purpose of it is to ensure the application’s functionality, reliability, security as well as performance.

Let’s discuss how your team approaches can get benefits of API Testing.

API Testing with Rest Assured

What is Rest Assured?

Rest stands for REpresentational State Transfer. Rest Assured is a java library to test restful Web services. It can be used to test XML and JSON based API.

How does it work?

1.Create HTTP requests (GET, POST etc.)
2. Send requests over the network.
3. Validate the received response.
4. Validate the response status code.

Now let’s take a deeper look at the HTTP methods

HTTP methods can be used for CRUD(Create-Read-Update-Delete) operations, and there are basic 5 types of methods being used widely.

GET : Read resources of given URL.
POST : Create new resources.
PUT : Updates a resource or creates new resources at a specified URL. It supports entire updates.
PATCH : Same as PUT but it supports partial updates.
DELETE : Delete resource at given URL.

There are still many HTTP methods used practically, you can take a closer look of them here: https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods

In API HTTP Response status code play pivotal role by providing necessary information about your API call, below we have mentioned the categories:

  1. Informational responses (100–199)
  2. Successful responses (200–299)
  3. Redirection message (300–399)
  4. Client error (400–499)
  5. Server error (500–599)

Source: https://en.wikipedia.org/wiki/List_of_HTTP_status_codes

Enough talk! let’s see how can we automate API using Rest Assured

What are prerequisites to test API using Rest Assured ?

  1. Java
  2. Maven
  3. Editor (IntelliJ, Eclipse)

Step 1 : Create a Maven Project in IntelliJ.

New Project → maven → Select Project SDK → Next → Project Name → Location → Finish

Step 2 : Open pom.xml file and add Maven dependencies.

<dependencies>
<dependency>
<groupId>io.rest-assured</groupId>
<artifactId>rest-assured</artifactId>
<version>4.5.0</version>
</dependency>
<dependency>
<groupId>org.testng</groupId>
<artifactId>testng</artifactId>
<version>7.5</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>2.8.9</version>
<!--<scope>provided</scope>-->
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>${jackson-databind-version}</version>
</dependency>
<dependency>
<groupId>javax.xml</groupId>
<artifactId>jaxb-impl</artifactId>
<version>${jaxb-impl-vesrion}</version>
</dependency>
</dependencies>

Step 3 : Create Java Class in src → test folder.

Right click on the test folder then new → java class .

Step 4 : Write Your Test cases Script to that java class.

package org.brit.tests;import io.restassured.builder.RequestSpecBuilder;
import io.restassured.filter.log.LogDetail;
import io.restassured.http.ContentType;
import io.restassured.specification.RequestSpecification;
import org.brit.tests.classes.StatusEnum;
import org.testng.annotations.Test;
import static io.restassured.RestAssured.given;
import static org.brit.tests.Constants.*;
import static org.brit.tests.actions.pets.PetsActions.PET_ENDPOINT;
import static org.hamcrest.CoreMatchers.equalTo;
import static org.hamcrest.CoreMatchers.is;
public class PetClassWithRequestSpec {
RequestSpecification requestSpecification = new RequestSpecBuilder()
.setBaseUri(BASE_URL)
.setContentType(ContentType.JSON)
.log(LogDetail.ALL).build();
@Test
public void getPetsByStatus() {
given().spec(requestSpecification).queryParam("status", StatusEnum.available.toString())
.get(PET_ENDPOINT + "/findByStatus")
.then().extract().body().jsonPath().prettyPrint();
}
@Test
public void getPetById() {
given().spec(requestSpecification)
.pathParam("petId", "499278344")
.get(PET_ENDPOINT + "/{petId}")
.then().extract().body().jsonPath().prettyPrint();
}
@Test
public void getPetByIdAndDoCheck() {
given().spec(requestSpecification)
.pathParam("petId", "499278344")
.when()
.get(PET_ENDPOINT + "/{petId}")
.then()
.statusCode(200)
.body("name", equalTo("Fido6"),
"id", is(499278344),
"status", equalTo("available"));
}
@Test
public void updateExistingPet() {
given().spec(requestSpecification)
.body("{\n" +
" \"id\": 499278344,\n" +
" \"name\": \"Fido6\",\n" +
" \"photoUrls\": [\n" +
" \"string\"\n" +
" ],\n" +
" \"tags\": [],\n" +
" \"status\": \"available\"\n" +
"}")
.put(PET_ENDPOINT)
.then().extract().body().jsonPath().prettyPrint();
given().spec(requestSpecification)
.pathParam("petId", "499278344")
.get(PET_ENDPOINT + "/{petId}")
.then()
.body("name", equalTo("Fido6"))
.extract().body().jsonPath()
.prettyPrint();
}
@Test
public void addNewPet() {
given()
.body("{\n" +
" \"id\": 89898888,\n" +
" \"name\": \"MyLittlePet\",\n" +
" \"photoUrls\": [],\n" +
" \"tags\": [],\n" +
" \"status\": \"" + StatusEnum.available.toString() + "\"\n" +
"}")
.post("https://petstore.swagger.io/v2/pet");
}}

Step 5 : Right click on java class code and select Run to run testcases.

Let’s take closer look to important topic

RequestSpecification

When we have many tests having some common specification to create a request, requestspecification can be used. We can define base URL, base path, header etc. We have to use the given() method of the restassured class to get reference of requestspecification.

Note: RequestSpecification is an interface therefore we can’t create an object of that.

ResponseSpecification

We have to use the then() method of the restassured class for responseSpecification.
Here is sample code,

RequestSpecification requestSpecification = new RequestSpecBuilder()
.setBaseUri(BASE_URL)
.setContentType(ContentType.JSON)
.log(LogDetail.ALL).build();
public void getPetsByStatus() {
given().spec(requestSpecification).queryParam("status", StatusEnum.available.toString())
.get(PET_ENDPOINT + "/findByStatus")
.then().extract().body().jsonPath().prettyPrint();
}

API Testing with Cucumber

What is Cucumber?

Cucumber is a software testing tool which follows behaviour Driven Development to write test cases. It is open source testing tools and enables testers to write code in simple english language.

What is BDD Framework?

BDD is Behaviour Driven Development. It is a technique of agile software development. It supports syntax like Given(), When() and Then() notations. It is powerful collaboration tool for whole team because it is using simple language therefore every technical and nontechnical can understand. BDD is very helpful for engineers, testers and also for users.

  1. given() — We can specify all the input . i.e path parameter, query parameter, header, body(payload).
  2. when() — Here we specify http request.
  3. then() — Here we validate response of request . i.e status code, response body etc.

Now Let’s see Most Important File in Cucumber

  1. Feature File
  2. Step Definition File
  3. Runner class

Let’s understand this file by example of cucumber using selenium briefly,
Feature File

Feature File is a root of cucumber. Features file contains high level description of the Test Scenario in simple language. It is known as Gherkin. It can be written in BDD framework.

Explanation of feature file keyword,
Feature:
Name of the feature which will be tested in test cases.
Scenario: Define steps and output for test cases.
Given: Precondition before testcase run.
And: Additional conditions for the test.
When: Specify conditions to execute further steps.
Then: Postcondition means after executing the test case result of it.

Below is sample feature file

Feature: As an amazon user I should br able to login and add a product to cartScenario: Login to amazon app
Given I am on login page of "https://www.amazon.com/"
Then I click on sign in button
Then I navigate to signin page
When I enter Username as "6354406931"
Then I click on continue button
When I enter Password as "Harsha@29"
Then I click on login button
Then I am logged in now
Scenario: Search an item and item into cart
Given I looking for "boat earphones"
Then I got list of earphones
Then I select Second item
When I click on item
Then I add it to cart

Step Definition file

Step definition class defines each scenario which is written in the feature file of cucumber project. So step definition plays a middle role between feature file and runner class.

Below is step definition class for above scenario

package smoke.stepDefinition;import core.pageobject.BasePO;
import io.cucumber.java.en.Given;
import io.cucumber.java.en.Then;
import io.cucumber.java.en.When;
public class MyAmazonStepdefinition extends BasePO {LoginPage loginPage = new LoginPage();
Search search = new Search();
@Given("I am on login page of {string}")
public void iAmOnLoginPageOf(String arg0) {
getDriver().get(arg0);
}
@Then("I click on sign in button")
public void i_click_on_sign_in_button() {
loginPage.clicksigninButton();
}
@Then("I navigate to signin page")
public void i_navigate_to_signin_page() {
System.out.println("I am on login page");
}
@When("I enter Username as {string}")
public void iEnterUsernameAs(String arg0) {
loginPage.setEmailEditText(arg0);
loginPage.fillEmailEditText();
}
@Then("I click on continue button")
public void i_click_on_continue_button() {
loginPage.clickContinueButton();
}
@When("I enter Password as {string}")
public void iEnterPasswordAs(String arg0) {
loginPage.setPasswordEditText(arg0);
loginPage.fillPasswordEditText();
}
@Then("I click on login button")
public void i_click_on_login_button() {
loginPage.clickOnLogInButton();
}
@Then("I am logged in now")
public void i_am_logged_in_now() {
System.out.println("I logged in succeesfully !!!!!!");
}
@Given("I looking for {string}")
public void iLookingFor(String arg0) {
search.setSearchField(arg0);
search.fillSearchfield();
}
@Then("I got list of earphones")
public void iGotListOfEarphones() {
search.clickOnSearchButton();
}
@Then("I select Second item")
public void iSelectSecondItem() {
System.out.println("Second item is selected");
}
@When("I click on item")
public void iClickOnItem() {
search.clickonIteam();
}
@Then("I add it to cart")
public void iAddItToCart() {
search.clickonAddToCart();
System.out.println("Item is added to cart");
}
}

Now, We have the feature file and step definition file ready. We can create a runner class to run them.

Runner File

A runner class will help us to run step definition files. Below is the runner class to run the above feature

package smoke.runner;
import io.cucumber.junit.Cucumber;
import io.cucumber.junit.CucumberOptions;
import org.junit.runner.RunWith;
@RunWith(Cucumber.class)
@CucumberOptions(features = "src/test/resources/amazon.feature" , glue ={"smoke/stepDefinition/"} )
public class TestRunner {
}

let’s see how can we automate API using Cucumber,

What are prerequisites to test API using Cucumber ?

  1. Java JDK
  2. Maven
  3. Editor (IntelliJ , Eclipse etc.)

Step 1: Create a maven Project in IntelliJ IDE.

New Project → maven → Select Project SDK → Next → Project Name → Location → Finish

Step 2: Open pom.xml file and add Cucumber dependency.

<dependencies>
<!-- https://mvnrepository.com/artifact/org.seleniumhq.selenium/selenium-java -->
<dependency>
<groupId>org.seleniumhq.selenium</groupId>
<artifactId>selenium-java</artifactId>
<version>4.1.2</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.testng/testng -->
<dependency>
<groupId>org.testng</groupId>
<artifactId>testng</artifactId>
<version>7.5</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.cucumber</groupId>
<artifactId>cucumber-java</artifactId>
<version>7.2.3</version>
</dependency>
<!-- https://mvnrepository.com/artifact/io.cucumber/cucumber-junit -->
<dependency>
<groupId>io.cucumber</groupId>
<artifactId>cucumber-junit</artifactId>
<version>7.2.3</version>
<scope>test</scope>
</dependency>
</dependencies>

Step 3: Create Feature file in src → main→resources

Feature: Test CRUD Methods on pet Rest api testing
This feature include testcases for pet store
Scenario: Update existing pet
Given I navigate to baseurl "https://petstore.swagger.io/v2/pet"
When I pass body parameter "id" as "9223372016854970402" and "name" as "string1"
Then Check update is done or not
Scenario: Get pet by id
Given I navigate to baseuri and pass "0" to "petId"
Scenario: Get pet by id and status
Given I navigate to url "https://petstore.swagger.io/v2"
Scenario: Delete a pet from list
Given navigate to base url
When "petId" is "898988888" delete pet from list
Then Check pet is found or not

Step 4: Create Java Class in src → test → java folder.

Right click on the test folder then new → java class .

Step 5: Put your cursor on scenario step and click on create step definition. Do it for all the steps and write your definition code in java class.

package TestCases;
import io.cucumber.java.en.Then;
import io.cucumber.java.en.When;
import io.restassured.http.ContentType;
import org.junit.Assert;
import tests.Authentication;
import tests.classes.StatusEnum;
import io.cucumber.java.en.Given;
import tests.classes.MessageResponse;
import java.util.HashMap;
import static io.restassured.RestAssured.given;
import static tests.Constants.BASE_URL;
public class PetTestcases {
public static String PET_ENDPOINT = BASE_URL + "/pet";
@Given("I navigate to url {string}")
public void iNavigateToUrlHttpsPetstoreSwaggerIoV(String arg0) {
given()
.baseUri(arg0)
.log().everything()
.contentType(ContentType.JSON)
.queryParam("status", StatusEnum.available.toString())
.when()
.get(PET_ENDPOINT + "/findByStatus")
.then()
.extract()
.body()
.jsonPath()
.prettyPrint();
}
@Given("I navigate to baseuri and pass {string} to {string}")
public void iNavigateToBaseuriAndPassTo(String arg0, String arg1) {
given()
.baseUri(BASE_URL)
.log().everything()
.contentType(ContentType.JSON)
.pathParam(arg1, arg0)
.get(PET_ENDPOINT + "/{petId}")
.getBody()
.prettyPrint();
}
@Given("I navigate to baseurl {string}")
public void iNavigateToBaseurl(String arg0) {
given().baseUri(arg0);
}@When("I pass body parameter {string} as {string} and {string} as {string}")
public void iPassBodyParameterAsAndAs(String arg0, String arg1, String arg2, String arg3) {
HashMap<String, String> map = new HashMap<>();
map.put(arg0, arg1);
map.put(arg2, arg3);
given().body(map).put(PET_ENDPOINT).then();
}@Then("Check update is done or not")
public void checkUpdateIsDoneOrNot() {
given()
.baseUri(BASE_URL)
.log().everything()
.contentType(ContentType.JSON)
.pathParam("petId", "9223372016854970402")
.get(PET_ENDPOINT + "/{petId}")
.then()
//.body("name", equalTo("Fido6"))
.extract().body().jsonPath()
.prettyPrint();
}
@Given("Navigate to pet url {string}")
public void navigateToPetUrl(String arg0) {
given().baseUri(arg0).body("{\n" +
" \"id\": 89898888,\n" +
" \"name\": \"MyLittlePet\",\n" +
" \"photoUrls\": [],\n" +
" \"tags\": [],\n" +
" \"status\": \"" + StatusEnum.available.toString() + "\"\n" +
"}")
.post();
}
@Given("navigate to base url")
public void navigateToBaseUrl() {
given().baseUri(BASE_URL).log().everything().contentType(ContentType.JSON).
header("api_key", Authentication.Login("britka","12345678"));
}
@When("{string} is {string} delete pet from list")
public void isDeletePetFromList(String arg0, String arg1) {
given().pathParam(arg0,arg1).when().delete(PET_ENDPOINT + "{petId}");
}
@Then("Check pet is found or not")
public void checkPetIsFoundOrNot() {
Assert.assertEquals(
given()
.baseUri(BASE_URL)
.log().everything()
.contentType(ContentType.JSON)
.pathParam("petId", "898988888")
.get(PET_ENDPOINT + "/{petId}")
.then()
.extract().body().jsonPath().getObject("", MessageResponse.class)
.getMessage(), "Pet not found");
}
}

Step 6: Create runner class src → test → java folder.

package TestRunner;
import io.cucumber.junit.Cucumber;
import io.cucumber.junit.CucumberOptions;
import org.junit.runner.RunWith;
@RunWith(Cucumber.class)
@CucumberOptions(features = "src/main/resources" , glue = {"TestCases"})
public class Run {
}

Note: Here features are defined as path for feature file and glue as path for step definition file.

Step 7 : Right click on runner class and select run.

Output:

Let’s see some Important Concept in Cucumber

Scenario Outline: It is used to test the same scenario using different data sets. In the “Examples” we can pass data. i.e For login scenarios of different users we can use scenario outlines like,

Feature: Login functionality using scenario outlines.
Scenario outline : Login to base URL
Given Navigate to base URL
When I enter correct “<username>” and “<password>”
Then Login successfully.
Examples:
|username |password|
| xyz107 | 123456 |

Data table: When we have to test numerous parameters, we can move to the data table. i.e For new users to sign up using several details,

Feature: New users sign up.
Scenario: Sign up to facebook
Given sign up using following details
|first_name|last_name |mobile_no |
|jitali | patel | 123456789|
Then users sign up successfully.

--

--

Alphabin Technology Consulting

Alphabin is an innovative QA and Software Testing Company headquartered in India and we are globally present such as UK, & Germany, USA. Let's discuss with us!