Skip to main content

API Test automation with REST Assured


Introduction

REST assured is an open source Java library widely used among many of the companies. It provides a domain-specific language (DSL) for writing powerful, maintainable tests for RESTful API.

Developing tool

  • IntelliJ IDEA community version would be enough

Framework / Tool / Language
  • Maven: It is a build automation tool used primarily for Java project
  • Java
  • TestNG

Create a maven project via IntelliJ IDEA

Step 1. Open IntelliJ IDEA and create a new maven project
File ā†’ New ā†’ Project

Step 2 :
  • Give relevant ArtifactId and GroupId and provide the path where the project to be saved.
  • You don't need to add any required jar files manually. Maven will import all the relevant JAR files for you. All you have to do is specify the dependencies with the specific versions in the pom file. since we are going to use TestNG and REST Assured we will add them in the pom file.
<dependencies>
        <dependency>
            <groupId>io.rest-assured</groupId>
            <artifactId>rest-assured</artifactId>
            <version>4.1.1</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.testng</groupId>
            <artifactId>testng</artifactId>
            <version>6.14.3</version>
        </dependency>
        <dependency>
</dependencies>

  • Add following build plugins and properties in pom.xml, In testng file, we define the packages to be executed.
<build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-surefire-plugin</artifactId>
                <version>2.19.1</version>
                <configuration>
                    <suiteXmlFiles>
                        <suiteXmlFile>testng.xml</suiteXmlFile>
                    </suiteXmlFiles>
                </configuration>
            </plugin>
        </plugins>
    </build>

  • Once you have added the dependencies, a popup message will be shown in the bottom saying ā€˜Import Changesā€™. Click on it to import the jars into the Library.

POST request

1. First I have created a Class to provide the base path, port, host, and token to be used for each requests.

package base;

import io.restassured.RestAssured;
import org.testng.annotations.BeforeClass;

public class FunctionalTest {

    public static String token = "<Token to be used>";

    @BeforeClass
    public static void setup() {
    
        String port = System.getProperty("server.port");
        if (port == null) {
            RestAssured.port = Integer.valueOf(<portNo>);
        } else {
            RestAssured.port = Integer.valueOf(port);
        }
        String basePath = System.getProperty("server.base");
        if (basePath == null) {
            basePath = "</api/test>";
        }
        RestAssured.basePath = basePath;

        String baseHost = System.getProperty("server.host");
        if (baseHost == null) {
            baseHost = "http://localhost";
        }
        RestAssured.baseURI = baseHost;
    }
}

2. Secondly, I have created a common class called TestRequests.java and extended the FunctionalTest class, in order to use @BeforeClass method and the token.

import base.FunctionalTest;
import io.restassured.http.ContentType;
import io.restassured.response.Response;
import org.apache.commons.lang3.RandomStringUtils;
import org.json.simple.JSONObject;
import org.json.simple.parser.ParseException;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import static io.restassured.RestAssured.given;

public class TestRequests extends FunctionalTest{
    String filePath="src/test/java/item/responseofPost.json"; //The location of the path the response to get saved
    String ItemName_post = "Item1";
    String ItemName_put = "Item2";
    private static Response response;

    @DataProvider(name = "data-provider")
    public Object[][] dataProviderMethod() {
        return new Object[][]{{"/items"}};
    }
    @Test(dataProvider = "data-provider", priority = 1)
    public void postReq(String pathName) throws IOException {

        String payload = "{\"name\":\""+ItemName_post+"\",\"description\":\"Description\"}";
        response = given().header("Authorization", "Bearer " + token).contentType(ContentType.JSON)
                .body(payload)
                .when()
                .post(pathName)
                .then()
                .statusCode(201)
                .extract()
                .response();
        System.out.println(response.asString());
        FileWriter file = new FileWriter(filePath);
        file.write(response.asString());
        file.flush();
        file.close();
    }
}
  • @DataProvider - An important feature provided by TestNG is the testng DataProvider feature. It is a method annotated with @DataProvider, Which returns an array of object, here I have returned the method argument using Data provider.
  • @Test - @Test annotation is the important part, where we write code/business logic. If something needs to be automated, that particular code needs to be inserted into the test method. The test method then executes @Test by passing attributes.
  • @BeforeClass - It will execute only once before the first test method in that particular class is invoked. You can then initialize or configure set-up for all the conventional test methods
1. In my POST request, I have specified the body request as payload, then passing the body to the endpoint and checking whether the received HTTP status code is 201

2. Once I check the status code I am extracting the response and saving in as a JSON format since I have to use the id for my next request

Sample JSON response of the POST request

{ 
   "name":"Item1",
   "description":"desc1",
   "updated_at":"2019-10-21 11:22:38",
   "created_at":"2019-10-21 11:22:38",
   "id":9
}

GET Request

  • I have written a small method to read the id from the saved JSON response file, which is going to be used in GET request
public Object getItemID() {
        JSONParser parser = new JSONParser();
        Object obj = null;
        try {
            obj = parser.parse(new FileReader(filePath));
        } catch (IOException e) {
            e.printStackTrace();
        } catch (ParseException e) {
            e.printStackTrace();
        }

        JSONObject jsonObject = (JSONObject) obj;
        Object id = jsonObject.get("id");
        System.out.println(id);
        return id;
    }

Make sure you have added json-simple dependency in the pom file.

<dependency>
     <groupId>com.googlecode.json-simple</groupId>
     <artifactId>json-simple</artifactId>
     <version>1.1</version>
 </dependency>

GET the response By ID

@Test(dataProvider = "data-provider", priority = 2)
    public void getReq(String pathName) {

        given().header("Authorization", "Bearer " + FunctionalTest.token)
                .when()
                .get(pathName + "/" + getItemID())
                .then()
                .statusCode(200).extract().response().prettyPrint();
    }

Here I am checking whether the status code is 200 and printing the response on the console.

PUT Request

@Test(dataProvider = "data-provider", priority = 3)
    public void putReq(String pathName) {

        String payload = "{\"name\":\""+ItemName_put+"\",\"description\":\"mock\"}";

        response = given().header("Authorization", "Bearer " +  token)
                .contentType(ContentType.JSON)
                .body(payload)
                .put(pathName + "/" + getItemID())
                .then()
                .statusCode(200).extract().response();
        JsonPath jsonPathEvaluater=response.jsonPath();

        String nameString=jsonPathEvaluater.get("name");
        String desc=jsonPathEvaluater.getString("description");
        Assert.assertTrue(nameString.equalsIgnoreCase(ItemName_put));
        Assert.assertTrue(desc.equalsIgnoreCase("mock"));
    }

In PUT request, Iā€™m changing the name and the description.

1. Assertion check on name and description.

2. Checking whether the status code is 200.

DELETE Request

@Test(dataProvider = "data-provider", priority = 5)
public void deleteRequestTest(String pathName) {

    given().header("Authorization", "Bearer " +  token)
            .contentType(ContentType.JSON).
            delete(pathName + "/" + getItemID()).
            then()
            .assertThat().statusCode(204);

}

1. Checking whether the status code is 204.

TestNG Report configuration

Add following dependencies in the pom file


 <dependency>
            <groupId>com.google.inject</groupId>
            <artifactId>guice</artifactId>
            <version>4.2.2</version>
        </dependency>
        <dependency>
            <groupId>org.uncommons</groupId>
            <artifactId>reportng</artifactId>
            <version>1.1.4</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>velocity</groupId>
            <artifactId>velocity-dep</artifactId>
            <version>1.4</version>
 </dependency>

Run the tests

  1. Go to the project path
  2. Run this command to execute the test cases
         : mvn clean test

     3. Now it will generate the test cases according to the order of the TestNG             priority
     4. The generated report can be found in the below mentioned path

          target -> surefire -reports ā†’ html




Complete code with CRUD operations

package Item;

import base2.FunctionalTest;
import io.restassured.http.ContentType;
import io.restassured.path.json.JsonPath;
import io.restassured.response.Response;
import org.apache.commons.lang3.RandomStringUtils;
import org.json.simple.JSONObject;
import org.json.simple.parser.ParseException;
import org.testng.Assert;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Ignore;
import org.testng.annotations.Test;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import static io.restassured.RestAssured.given;

public class ReportRequestTest extends FunctionalTest {
    String filePath = "src/test/java/item/responseofPost.json";
    String ItemName_post = "Item1";
    String ItemName_put = "Item2";
    String generatedString = RandomStringUtils.randomAlphanumeric(10);

    private static Response response;

    @DataProvider(name = "data-provider")
    public Object[][] dataProviderMethod() {
        return new Object[][]{{"/items"}};
    }

    @Test(dataProvider = "data-provider", priority = 1)
    public void postReq(String pathName) throws IOException {

        String payload = "{\"name\":\"" + ItemName_post + "\",\"description\":\"desc1\"}";
        response = given().header("Authorization", "Bearer " + token).contentType(ContentType.JSON)
                .body(payload)
                .when()
                .post(pathName)
                .then()
                .statusCode(201)
                .extract()
                .response();
        System.out.println(response.asString());
        FileWriter file = new FileWriter(filePath);
        file.write(response.asString());
        file.flush();
        file.close();
    }

    @Test(dataProvider = "data-provider", priority = 2)
    public void getReq(String pathName) {

        given().header("Authorization", "Bearer " + FunctionalTest.token)
                .when()
                .get(pathName + "/" + getItemID())
                .then()
                .statusCode(200).extract().response().prettyPrint();
    }

    @Test(dataProvider = "data-provider", priority = 3)
    public void putReq(String pathName) {

        String payload = "{\"name\":\"" + ItemName_put + "\",\"description\":\"mock\"}";

        response = given().header("Authorization", "Bearer " + token)
                .contentType(ContentType.JSON)
                .body(payload)
                .put(pathName + "/" + getItemID())
                .then()
                .statusCode(200).extract().response();

        JsonPath jsonPathEvaluater = response.jsonPath();

        String nameString = jsonPathEvaluater.get("name");
        String desc = jsonPathEvaluater.getString("description");
        Assert.assertTrue(nameString.equalsIgnoreCase(ItemName_put));
        Assert.assertTrue(desc.equalsIgnoreCase("mock"));
    }

    @Test(dataProvider = "data-provider", priority = 4)
    public void getAll(String pathName) {
        given().header("Authorization", "Bearer " + token)
                .when()
                .get(pathName)
                .then()
                .statusCode(200).extract().response().prettyPrint();
    }

    @Test(dataProvider = "data-provider", priority = 5)
    public void deleteRequestTest(String pathName) {

        given().header("Authorization", "Bearer " + token)
                .contentType(ContentType.JSON).
                delete(pathName + "/" + getItemID()).
                then()
                .assertThat().statusCode(204);
    }

    public Object getItemID() {
        JSONParser parser = new JSONParser();

        Object obj = null;
        try {
            obj = parser.parse(new FileReader(filePath));
        } catch (IOException e) {
            e.printStackTrace();
        } catch (ParseException e) {
            e.printStackTrace();
        }
        JSONObject jsonObject = (JSONObject) obj;
        Object id = jsonObject.get("id");
        System.out.println(id);
        return id;
    }
}

pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<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>APITesting</groupId>
    <artifactId>APITesting</artifactId>
    <version>1.0-SNAPSHOT</version>
    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-surefire-plugin</artifactId>
                <version>2.19.1</version>
                <configuration>
                    <suiteXmlFiles>
                        <suiteXmlFile>testng.xml</suiteXmlFile>
                    </suiteXmlFiles>
                </configuration>
            </plugin>
        </plugins>
    </build>
    <!-- https://mvnrepository.com/artifact/io.rest-assured/rest-assured -->
    <dependencies>
        <dependency>
            <groupId>io.rest-assured</groupId>
            <artifactId>rest-assured</artifactId>
            <version>4.1.1</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.testng</groupId>
            <artifactId>testng</artifactId>
            <version>6.14.3</version>
        </dependency>
        <dependency>
            <groupId>io.rest-assured</groupId>
            <artifactId>rest-assured</artifactId>
            <version>3.1.1</version>
            <scope>compile</scope>
        </dependency>
        <dependency>
            <groupId>org.json</groupId>
            <artifactId>json</artifactId>
            <version>20080701</version>
        </dependency>
        <dependency>
            <groupId>com.googlecode.json-simple</groupId>
            <artifactId>json-simple</artifactId>
            <version>1.1</version>
        </dependency>
        <dependency>
            <groupId>com.google.inject</groupId>
            <artifactId>guice</artifactId>
            <version>4.2.2</version>
        </dependency>
        <dependency>
            <groupId>org.uncommons</groupId>
            <artifactId>reportng</artifactId>
            <version>1.1.4</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>velocity</groupId>
            <artifactId>velocity-dep</artifactId>
            <version>1.4</version>
        </dependency>
        <dependency>
            <groupId>io.rest-assured</groupId>
            <artifactId>json-path</artifactId>
            <version>3.0.0</version>
        </dependency>
    </dependencies>
    <properties>
        <maven.compiler.source>1.8</maven.compiler.source>
        <maven.compiler.target>1.8</maven.compiler.target>
    </properties>
</project>

Pros
  • Dedicated REST API automation framework, supports every HTTP request method, headers, params, built-in assertions
  • Open-source
  • Maintainable codes
Cons
  • Supports only Java language

References
http://www.appsdeveloperblog.com/rest-assured-evaluate-json-response-body/
http://rest-assured.io/


Comments

Popular posts from this blog

GitLab and Jenkins configuration through SSH

In my previous post I have mentioned how to integrate GitLab with Jenkins using username and password. Now we will learn how to configure Jenkins and GitLab using SSH connection. Login as Jenkins user sudo su - jenkins Run the following command to generate SSH key,  ssh - keygen Now it will create  a directory named .ssh if it doesn't exist, Press enter and re-enter when you are prompted to enter passphrase. thuvvareka : ~ jenkins$ ssh - keygen Generating public / private rsa key pair . Enter file in which to save the key ( / Users / Shared / Jenkins / . ssh / id_rsa ) : Created directory ' /Users/Shared/Jenkins/.ssh ' . Enter passphrase ( empty for no passphrase ) : Enter same passphrase again : Your identification has been saved in / Users / Shared / Jenkins / . ssh / id_rsa . Your public key has been saved in / Users / Shared / Jenkins / . ssh / id_rsa . pub . The key fingerprint is : SHA256 : O9APiAETUYC87e9T6k18SPFQxEN4R2gJbKG6JLOID64 jenkins@thu...

Mobile Test Automation using Appium and Android studio

In this article we will discuss about how to automate Mobile application using Appium Server and Android Studio. Appium supports both iOS and Android. Appium is HTTP server. It receives the commands from client, executes the command on Mobile device and send a HTTP response representing the result of the command execution. I am going to use Android studio to create a virtual emulator. And Selenium WebDriver will be used to write the Client. I would prefer to use the virtual emulator instead of using real device. In actual devices you may find difficulties to connect/detect it. Pre-requisites .apk file is required to install in Mobile device (Virtual emulator). Android Studio, Appium desktop server and intelliJ IDEA have to be installed. Virtual emulator This post guides you to create the Virtual emulator using Android Studio. Once you launch the emulator now It's time to install the mobile application which is going to be automated. Drag and drop the apk file ...

Katalon studio Execution Profiles

Hi Folks, I want to share my experience regarding the learning, My project manager asked me to find the best way to automate the web application for the regression/retest purpose. So I had a research on the tools and technologies regarding automation. So I found this :) In this post I would like to share my knowledge on Katalon Studio Profiles.  Let's have a quick idea regarding Katalon studio. Katalon studio is a free automation testing tool and supports the web and mobile environment, and built on top of the open-source automation frameworks Selenium, Appium with a specialized IDE. Pre requests - You can download Katalon studio from this link. I am using the latest version in order to avoid unnecessary errors. First, I will show how to record the Web application via Katalon studio. Find below mentioned test scenarios which are going to be recorded Launch the application (URL : http://demoaut.katalon.com/ ) Make an Appointment Login using provided credentials...