Showing posts with label REST. Show all posts
Showing posts with label REST. Show all posts

2.8.19

Testing APIs with RestAssured

These days there are many tools available to test REST based APIs - some of them are quite mature and feature-rich like Citrus, soapUI and Postman; but these are built only for API testing and trying to use them for other general purposes is often difficult.

If you already have a mature framework and want to 'incrementally' test APIs also as part of your existing codebase for functional automation, and want to save time in building a new framework around new tools, then you can use RestAssured in your existing framework.

RestAssured is a very capable java library for testing APIs and it even supports BDD-style spec.

Maven dependencies for Rest Assured -

<dependency>
<groupId>io.rest-assured</groupId>
<artifactId>rest-assured</artifactId>
<version>3.3.0</version>
</dependency>

<dependency>
<groupId>io.rest-assured</groupId>
<artifactId>json-path</artifactId>
<version>3.3.0</version>
</dependency>

<dependency>
<groupId>io.rest-assured</groupId>
<artifactId>xml-path</artifactId>
<version>3.3.0</version>
</dependency>

<dependency>
<groupId>io.rest-assured</groupId>
<artifactId>json-schema-validator</artifactId>
<version>3.3.0</version>
</dependency>


Sample code for working with RestAssured -

package main.java.com.automation.keyword.app;

import static io.restassured.RestAssured.*;
import static io.restassured.matcher.RestAssuredMatchers.*;
import static io.restassured.module.jsv.JsonSchemaValidator.*;
import static org.hamcrest.Matchers.*;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertTrue;
import org.apache.log4j.Logger;
import io.restassured.RestAssured;
import io.restassured.builder.RequestSpecBuilder;
import io.restassured.http.Header;
import io.restassured.http.Headers;
import io.restassured.path.json.JsonPath;
import io.restassured.response.Response;
import io.restassured.response.ValidatableResponse;
import io.restassured.specification.RequestSpecification;
import io.restassured.specification.ResponseSpecification;

public class RESTPoC {

private static Logger log = Logger.getLogger(RESTPoC.class.getName());

/*
* Variables for specification of different APIs though we may have only a single response specification
*/

private RequestSpecification raceReqSpec;

private RequestSpecification postmanReqSpec;

private ResponseSpecification respSpec;

private String url = "";

/*
* Function to set the config for all Req/Resp specifications
* But somehow its use is not getting implemented correctly as of now
*/

public void restConfig() {

log.info("setting proxy...");

//  RestAssured.proxy("localhost", 8888);

log.info("configuring common requestSpecification...");

RequestSpecification requestSpecification = new RequestSpecBuilder().

//    addHeader("Content-type", "json").
//    addHeader("Accept", "application/json").

build();

log.info("setting this as the specification for all REST requests...");

RestAssured.requestSpecification = requestSpecification;

}

public String getURL(String apiName) {

switch (apiName.toLowerCase()) {

case "google-books":
url = "https://www.googleapis.com/books/v1/volumes?q=isbn:0747532699";
break;
case "google-books-java":
url = "https://www.googleapis.com/books/v1/volumes?title:java";
break;
case "f1-api":
url = "http://ergast.com/api/f1/2018/circuits.json";
break;
case "postman-get":
url = "https://postman-echo.com/GET";
break;
case "400":
url = "http://ergast.com/api/f1/2018/circuits1.json";
break;
case "404":
url = "http://ergast.com/api/f1/2018/circuits.json 1";
break;
default:
break;
}

log.info("Request URL: " + url);
return url;
}

public String setURL() {

   url = "https://www.googleapis.com/books/v1/volumes?q=isbn:0747532699";
//   url = "http://ergast.com/api/f1/2018/circuits.json";
//   url = "https://postman-echo.com/GET";

log.info("Request URL: " + url);
return url;

}

/*
* This function does not take a Req Specification to get the Response from the resourceURL
* It has BDD style coding
* It also logs all requests and response steps
*/

public void getResponseBDD() {

given().log().all().

when().get(url).

then().log().all().statusCode(200);

}

/*
* This function does not take a Req Specification to get the Response from the resourceURL
* Nor does this uses BDD style coding
* @param resourceURL
*/

public Response getResponseDirectlyNoReqSpec(String resourceURL) {

Response rsp = null;

RequestSpecification rq = RestAssured.given();

rsp = rq.get(resourceURL);

log.info("------------------------------------------------------------------");

log.info("URL: " + resourceURL + " has Response: " + "\n" + rsp.asString());

log.info("------------------------------------------------------------------");

return rsp;
}

public Boolean chkInvalidResponse() {

Response rsp;

Boolean result;

//  rsp = getResponseDirectlyNoReqSpec(getURL("f1-api") + " 12312");

rsp = getResponseDirectlyNoReqSpec(getURL("404"));

if (getStatusCode(rsp) == 200) {

log.info("Valid response received");

result = true;

} else {

getStatusLine(rsp);
getAllHeaders(rsp);
result = false;
}
return result;
}

public void sampleJsonPathExp() {

Response rsp;

rsp = getResponseDirectlyNoReqSpec(getURL("google-books-java"));
JsonPath jp = rsp.jsonPath();
}

public void chkResponseGoogleBooksAPI() {

Response rsp = getResponseDirectlyNoReqSpec(getURL("google-books"));

if (getStatusCode(rsp) == 200) {

getAllHeaders(rsp);

} else {
getAllHeaders(rsp);
}
}

/*
* Function to check response of F1 API via JsonPath
*/
public void chkResponseF1API() {

Response rsp = getResponseDirectlyNoReqSpec(getURL("f1-api"));

String contentType = "";

//   Proceed only if response is 200

if (getStatusCode(rsp) == 200) {

getStatusLine(rsp);

getAllHeaders(rsp);

contentType = getHeaderValue(rsp, "Content-type");

getHeaderValue(rsp, "Server");

// Proceed only if response type is JSON

if (contentType.toLowerCase().contains("json")) {

JsonPath jp = rsp.jsonPath();

log.info("Series Name: " + jp.get("MRData.series").toString().toUpperCase());

log.info("Year: " + jp.get("MRData.CircuitTable.season"));

log.info("Circuit Name: " + jp.get("MRData.CircuitTable.Circuits[0].circuitName"));

log.info("Circuit Country: " + jp.get("MRData.CircuitTable.Circuits[0].Location.country"));

log.info("Total Circuits: " + jp.get("MRData.total"));

log.info("Getting name and country of each circuit -------------------------------------");

for (int i = 0; i < Integer.parseInt(jp.get("MRData.total")); i++) {

log.info("Circuit Name: " + jp.get("MRData.CircuitTable.Circuits[" + i + "].circuitName"));

log.info("Circuit Country: " + jp.get("MRData.CircuitTable.Circuits[" + i + "].Location.country"));

}
}
}

// TestNG Assert library

assertTrue(contentType.toLowerCase().contains("json"));

//  assertEquals(contentType, "application/json");
}

// Status Code is of type int
public int getStatusCode(Response response) {

int statusCode;
statusCode = response.getStatusCode();
log.info("Status Code: " + statusCode);
return statusCode;
}

// Status msg is of type string
public String getStatusLine(Response response) {

String statusLine;

statusLine = response.getStatusLine() + "";

log.info("Status Msg: " + statusLine);

return statusLine;
}

public String getHeaderValue(Response response, String headerName) {

String headerValue = "";

headerValue = response.getHeader(headerName) + "";

log.info("Header name: " + headerName + " - value: " + headerValue);

return headerValue;
}

public void getAllHeaders(Response response) {

log.info("Getting value of all Headers via Headers object ---------------------------------");

Headers allHeaders = response.getHeaders();

for (Header header : allHeaders) {

log.info("Header name: " + header.getName() + " - value: " + header.getValue());

}
}

/*
* Keyword sort of methods Invoking requests without first calling the config Req/Resp is successful when common
* spec for response is not used
*/
public void invokeRestNoConfig() {
getURL("f1-api");
getResponseBDD();
}

public static void main(String[] args) {

RESTPoC rd = new RESTPoC();
rd.chkResponseF1API();
rd.chkResponseGoogleBooksAPI();
rd.chkInvalidResponse();
rd.sampleJsonPathExp();

}

}