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

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...

Protractor with Gitlab and Jenkins

Hi everyone.. welcome to the first article in my new series of articles on Automation Testing. For a change, let's start from the End. Let's assume you have written your automation code in protractor and your project is ready to be pushed in to the repository. So let's start with a brief introduction on how to push our automation code to a Git repository. In this lesson I will be using GitLab repository. First things first.. You can't just push the code to a repository. Yeah.... you have to install Gitlab and make sure you have configured it properly. Try following command to make sure Git have been installed in your machine. git --version Hope Git have been installed in your machine, Let's start with GitLab configuration. Sign up with GitLab account Go to GitLab account and get register with your email account To identify you as the author configure your Git username and email address in your machine git config -- global user.name git config -- g...

Data Driven Protractor Testing

In this article I would like to share knowledge regarding Data driven testing. When using a Data driven automation test framework, we do not need to hard code the test data. Instead it enables to access the test data from a separate data file and use them in the automated test cases. First, let's take a look at a simple Protractor script without Data Driven framework describe('Angular home page', function () {       it('should add the String in todo list ', function () {          browser.get('https://angularjs.org/');          element.all(by.css("[placeholder='add new todo here']")).sendKeys("Add POM");          element(by.css('input.btn-primary')).click();          var getText = element.all(by.css('label.checkbox'));          getText.get(2).getText().then(function (results) {          expect(results).toEqua...