Thursday, July 30, 2020

Data Driven Testing for REST GET Method

GET some REST with API Test using Data Driven:

 In the last post we have seen how to work on GET method using Rest Assured. But it was tested for the using single value and its hard coded. What if the requirement is like to test different set of test data. In this case we need to go to DataDriven testing reading data from external sources like XML, Excel, CSV or data files.

 So here in this post we will see how to feed data to the GET REST request using data from external source. Here I will be using Excel file for the test data. I have prepared some sample data for the testing purpose. Below is the test data, this is  how my test data in excel file looks like.


SI.No

InputData

Expected_FieldName

Expected_Value

1

INR

name

India

2

INR

name;capital;languages.name;region

India;New Delhi;Hindi;Asia

3

NOK

name;capital;languages.name

Norway;Oslo;Norwegian

 1st Column is for Serial number column

 2nd Column is for Input data, that we are passing in GET method to retrieve the details of the entered value

 3rd Column contains the expected field names from the response received. Here we are concatenated the expected field with comma separated. Consider if you want to verify more than one field in response so we can pass like this.

 4th Column contains the expected field value from the response received. Example from 3rd column for first record I am expecting only name field and value as India. Again, in second records I am expecting name, capital, language name and region so same way I am expecting value from that field. Make sure expected field name and expected value column should same number of arguments. If we are expecting blank value in field just blank value.

 Now we need to write a code to read the data from excel file and it in our GET method. So, there are many ways to read the data from excel and mainly Apache POI or JXL is used. Here in my post I am using JXL jar for reading the test data from Excel file. Below is the code for the same.

            String strTestDataPath = "C:/Testdata/TestData_Currency.xls";
            String strTestDataSheet = "Currency";
            Workbook wrkBookOBj = Workbook.getWorkbook(new File(strTestDataPath));
            Sheet sheet = wrkBookOBj.getSheet(strTestDataSheet);
            int rRows = sheet.getRows();

strCurrencyName = sheet.getCell(1,Row).getContents();

strExpFieldNames = sheet.getCell(2,Row).getContents();

strExpFieldValues = sheet.getCell(3,Row).getContents();


strCurrencyName: Contains the data from 1st column i.e. Input data column.
strExpFieldNames: Contains the data from 2nd column i.e. Expected field name.
strExpFieldValues: Contains the data from 3rd column i.e. Expected value.

 Here, Column names are hard coded as 1,2,3 as we know these columns are fix and not dynamic so.

 To iterate the value till last row of the test data table we need to loop it using 'for.. loop' and also pass the test data to the GET method. The combined code looks like below.


             String strCurrencyName = null; String strExpFieldNames = null;
             String strExpFieldValues = null;
             String strTestDataFilePath "C:/Testdata/TestData_Currency.xls";
             String strTestDataSheetName "Currency";
            
             RestAssured.baseURI = "https://restcountries.eu/rest/v2/currency/";       
             RequestSpecification reqObj = RestAssured.given();            
             Response resObj = null;
            
    try {
        Workbook wrkBookOBj = Workbook.getWorkbook(new File(strTestDataFilePath);
                    Sheet sheet = wrkBookOBj.getSheet(strTestDataSheetName);
                    int rRows = sheet.getRows();
                    int i = 0;
                   
                for(i=1;i<=rRows-1;i++) { //Rows loop                         
                     strCurrencyName = sheet.getCell(1,i).getContents();
                     strExpFieldNames = sheet.getCell(2,i).getContents();
                     strExpFieldValues = sheet.getCell(3,i).getContents();
                                
                     resObj = reqObj.request(Method.GET,strCurrencyName);

                //Rows loop Ends
                   
             } catch (BiffException e) {
                    e.printStackTrace();
             } catch (IOException e) {
                    e.printStackTrace();
             }
finally{
                   wrkBookOBj.Close();
                  }  

 Till now we all set to run the test with multiple set of test data. Now It’s time to read the response and we need to validate our expected field names and expected values. To do that we need to split “strExpFieldNames” and “strExpFieldValues” with the comma “;” separated, here we will get expected field name expected values and compare with the actual values and field name read from response. Below is the code for the splitting the values and assigning it to an array and iterate using for loop for all the expected field name and values we are expecting.

 Once we got the “extFieldName” expected field name, we need to pass that variable to fetch it’s value from the response. After successfully reading the actual value from the response compare with the expected values, if both are matches then print as “PASS” or else print as “FAIL”.


            String strExpFieldName[] = strExpFieldNames.split(";");
            String strExpFieldValue[] = strExpFieldValues.split(";");
            
             for(int x = 0;x<=strExpFieldName.length-1;x++) {
              String extFieldName = strExpFieldName[x];
              String extFieldValue = strExpFieldValue[x];
                   
              String strActFieldValuesresObj.jsonPath().get(extFieldName)
                                                    .toString().replace("[","").replace("]","");
              String strActFieldValue[] = strActFieldValues.split(",");
                   
        boolean temp = false;                 
      for(int z = 0;z<=strActFieldValue.length-1;z++) {
        if(strActFieldValue[z].trim().equalsIgnoreCase(extFieldValue.trim())) {
           System.out.println("PASS");
            temp = true;
            break;
           }                                            
           if((!temp) && z == strActFieldValue.length-1) {
             System.out.println("FAIL");
            }                  
         }
           if(temp && x==strExpFieldName.length-1) {
              break;
             }
        }
                 }

 Now I will put above code into one method with that our code also looks neat and clean and this method can be reused for another class another test.

 Here I am passing expected field, expected values and Response object. By using Response object we can read the response content and retrieve the expected field values.

    public static void fnCheckResult(String ExpFields, String ExpValues, Response resObj){

             String strExpFieldName[] = ExpField.split(";");
             String strExpFieldValue[] = ExpValues.split(";");
            
             for(int x = 0;x<=strExpFieldName.length-1;x++) {
                String extFieldName = strExpFieldName[x];
                String extFieldValue = strExpFieldValue[x];
                   
                String strActFieldValues = resObj.jsonPath()
.get(extFieldName)
                                                              .toString() .replace("[","").replace("]","");
                String strActFieldValue[] = strActFieldValues.split(",");
                   
              boolean temp = false;                 
           for(int z = 0;z<=strActFieldValue.length-1;z++){                                                              if(strActFieldValue[z].trim().equalsIgnoreCase(extFieldValue.trim())) {
            
               System.out.println("PASS");
               temp = true;
               break;
              }                                            
              if((!temp) && z == strActFieldValue.length-1) {        
                  System.out.println("FAIL");
                }                  
            }
              if(temp && x==strExpFieldName.length-1) {
                  break;
                        }
                    }
               }
          }

So finally our class looks something like this as below.

**************************************************************************
package test.rest.practice;     
import java.io.File;
import java.io.IOException;
import io.restassured.RestAssured;
import io.restassured.http.Method;
import io.restassured.response.Response;
import io.restassured.specification.RequestSpecification;
import jxl.Sheet;
import jxl.Workbook;
import jxl.read.biff.BiffException;
 
public class HTTPGETTestREST {
       static Workbook wrkBookOBj = null;
       static Sheet sheet = null;
 
 public static void main(String arg[]) {
  String strCurrencyName = null; String strExpFieldNames = null;
  String strExpFieldValues = null;
  String strTestDataPath = "C:/TestRESTPractice/Testdata/TestData_Currency.xls";
  String strTestDataSheet = "Currency";
            
   RestAssured.baseURI = "https://restcountries.eu/rest/v2/currency/";      
   RequestSpecification reqObj = RestAssured.given();            
   Response resObj = null;
    try {
       wrkBookOBj = Workbook.getWorkbook(new File(strTestDataPath));
       sheet = wrkBookOBj.getSheet(strTestDataSheet);
       int rRows = sheet.getRows();
       int i = 0;
 
        for(i=1;i<=rRows-1;i++) { //Rows loop                     
          strCurrencyName = sheet.getCell(1,i).getContents();
          strExpFieldNames = sheet.getCell(2,i).getContents();
          strExpFieldValues = sheet.getCell(3,i).getContents();
          resObj = reqObj.request(Method.GET,strCurrencyName);
   //Calling check result method and passing fieldname, field value and response object
        if(resObj.getStatusCode()==200){
                    fnCheckResult(strExpFieldNamesstrExpFieldValuesresObj); 
                    
 
        }  //Rows loop Ends
      } catch (BiffException e) {
              e.printStackTrace();
      } catch (IOException e) {
              e.printStackTrace();
      }finally{
                   wrkBookOBj.Close();
                  }  
}     
      
**************************************************************************
   public static void fnCheckResult(String ExpFields, String ExpValues, Response resObj){
       String strExpFieldName[] = ExpField.split(";");
       String strExpFieldValue[] = ExpValues.split(";");
            
        for(int x = 0;x<=strExpFieldName.length-1;x++) {
         String extFieldName = strExpFieldName[x];
         String extFieldValue = strExpFieldValue[x];
                   
         String strActFieldValues = resObj.jsonPath()
 .get(extFieldName)
                                              .toString() .replace("[","").replace("]","");
         String strActFieldValue[] = strActFieldValues.split(",");
                   
          boolean temp = false;                 
          for(int z = 0;z<=strActFieldValue.length-1;z++) {
            if(strActFieldValue[z].trim().equalsIgnoreCase(extFieldValue.trim())) {                                    System.out.println("PASS");
               temp = true;
               break;
             }                                            
             if((!temp) && z == strActFieldValue.length-1) {                                                                      System.out.println("FAIL");
               }                  
          }
             if(temp && x==strExpFieldName.length-1) {
                 break;
            }
        }
    }
}
**************************************************************************

Still have any open questions put them in comments i will try best to resolve.


                         That’s all Folks.



Friday, July 24, 2020

GET the most of From REST

Use of GET Method in REST

 In previous blog we got to know the features and functionality of the REST services. Now we will see how different methods of REST can be used in our testing activities.

 First of all, we will see what the pre-requisite are for automating the REST services. Below are the items required for testing REST service automation.

  • IDE – Eclipse or IntelliJ or any IDE for developing test automation script.
  • Maven dependencies – Below are dependencies are need to run REST tests
    • Rest-Assured – Contains all features need for REST Automation testing
    • TestNG – For running test and to use of TestNG features
    • JSONSimple – To read Json request and response and parsing
    • Apache POI or JXL – To read data from external sources like Excel files

 Why dependencies are need. Because we don't need to download and add jars to our project/s in IDE. So once dependencies added in 'pom.xml' automatically all required jars gets downloads.

 Now we have to create one Maven project in IDE (it can be Eclipse or any IDE, here I will be using Eclipse for all work). Once the maven project got created make sure you have added all the required dependencies as mentioned above. After adding dependencies 'pom.xml' will something looks like this.

 <?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>TestRESTPractice</groupId>

  <artifactId>TestRESTPractice</artifactId>

  <version>0.0.1-SNAPSHOT</version>

  <properties>

    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>

  </properties>

  <dependencies>

             <dependency>

                 <groupId>io.rest-assured</groupId>

                 <artifactId>rest-assured</artifactId>

                 <version>4.3.0</version>

                 <scope>test</scope>

             </dependency>      

             <dependency>

                 <groupId>org.testng</groupId>

                 <artifactId>testng</artifactId>

                 <version>7.1.0</version>

                 <scope>test</scope>

             </dependency>      

             <dependency>

                 <groupId>com.googlecode.json-simple</groupId>

                 <artifactId>json-simple</artifactId>

                 <version>1.1.1</version>

             </dependency>

             <dependency>

                 <groupId>org.apache.poi</groupId>

                 <artifactId>poi</artifactId>

                 <version>4.1.2</version>

             </dependency>

             <dependency>

                 <groupId>org.apache.poi</groupId>

                 <artifactId>poi-ooxml</artifactId>

                 <version>4.1.2</version>

             </dependency>

             <dependency>

                 <groupId>net.sourceforge.jexcelapi</groupId>

                 <artifactId>jxl</artifactId>

                 <version>2.6.12</version>

             </dependency>

  </dependencies>

        </project>

 At initially we need to make sure all the dependencies added are correct or to check is there any compilation error to check that select pom.xml from project explorer and right click on it and select Run as and select mvn clean, to clean the project. Once we see Build Success repeat same step and this time select mvn install, to install all dependencies to the project or to the repository. 

 In a maven project you have noticed that there two default folders get creates “src/main/java” and “src/test/java”. Here “src/main/java” is mainly for developers to put dev related works and “src/test/java” is for purely for testers for maintaining all testing tasks. This is standard format for any framework, and its optional but not a mandatory to follow. 

 Its optional to create your own package or work on the default package. If you want to create package right click on the respective folder (as mentioned above please use “src/test/java”) select New -> package, provide your package name and click on Finish. 

 In same way create one java class just right click on package and click on New select Class, New -> class, give the Class as per your standards follow.

 Now I am going explain about the features of Rest Assured framework.

 We need to have base URI for any API testing it may be manual or Automation testing. Considering this I am going to use below mentioned base URI for this post.

 Sample REST API URL: https://restcountries.eu (Thank you https://restcountries.eu team)

 In this URL we can get all types of sample REST API’s

 For this post I am using GET API for reading currency and its URL is https://restcountries.eu/rest/v2/currency and this is our base URI and we need to pass currency name to retrieve the details of that particular currency.

 Now we need initialize the base URI as below,

  RestAssured.baseURI = "https://restcountries.eu/rest/v2/currency";  

 Once initialization of base URI is done now create object for rest request,

 RequestSpecification reqObj = RestAssured.given();

 Here RestAssured.given(), RestAssured is a class and given is method which reads the parameter. 

 Create object for response and provide the method name which method you want to use. Also pass the value or ID to retrieve the details for GET method.

 reqObj.request(Method.GET,"/INR");

 Here we see “reqObj” holds the Base URI and request content and “Method.GET” tells us to use which HTTP REST method to be used. After method name, we are passing parameter value which is the input data for the REST request. As per the URL and REST request here we are using “INR”, to retrieve the details of the currency INR. You can pass different currency to see the details of that currency.

 Once we put all together the actual code looks like below,

 RestAssured.baseURI = "https://restcountries.eu/rest/v2/currency";       RequestSpecification reqObj = RestAssured.given();

 reqObj.request(Method.GET,"/INR");

 You can keep the above code in main method of keep in TESTNG test method. For now, I am using it in main method and it looks like as below.

import io.restassured.RestAssured;

import io.restassured.http.Method;

import io.restassured.response.Response;

import io.restassured.specification.RequestSpecification;

 

public class GetTestClass {

    public static void main(String arg[]) {

             RestAssured.baseURI = "https://restcountries.eu/rest/v2/currency"

             RequestSpecification reqObj = RestAssured.given();

             reqObj.request(Method.GET,"/INR");                 

       }

}

 Till here we are successfully sent the request to the URI/server.

 Now it’s time to read the response received for the request which we sent. We need to create one response variable to capture all the response.


Response resObj = null;

resObj = reqObj.request(Method.GET,"/INR");    

 As mentioned above we are sending request using GET method and “INR” as input value as currency. Here “resObj” holds the response content.

 Print the response to see the content.

             System.out.println(resObj.getBody());

 Output of this will be like below,

Console output = io.restassured.internal.RestAssuredResponseImpl@753432a2 

since it is JSON format we need to convert it to string to see the actual response in String format so we need to use “.asString()”.

             System.out.println+resObj.getBody().asString());      

 Sample Output of this will be like below,

 Console output = [{"name":"Bhutan","topLevelDomain":[".bt"],"alpha2Code":"BT","alpha3Code":"BTN","callingCodes":["975"],…]

 If I want to see the response in pretty JSON format look, then we need to use “.prettyPrint()”

              System.out.println(resObj.getBody().prettyPrint());

 Sample Output of this will be like below,

 Console output =  [

    {

        "name": "Bhutan",

        "topLevelDomain": [

            ".bt"

        ],

        "alpha2Code": "BT",

        "alpha3Code": "BTN",

        "callingCodes": [

        "975"

        ],…]

 Once you got the success response and if you want to verify response status code, status line and other details, please refer the below table for few of them “resObj” which we created above for reading response.

Method Name

Syntax

Output

getStatusCode

resObj.getStatusCode()

200 for success response

getContentType

resObj.getContentType()

application/json;charset=utf-8

getStatusLine

resObj.getStatusLine()

HTTP/1.1 200

getTime

resObj.getTime()

3175 in milliseconds

getHeaders

resObj.getHeaders()

request/response header (can’t add here due to long string)

getDetailedCookies

resObj.getDetailedCookies()

http details cookies (can’t add here due to long string)

getCookies

resObj.getCookies()

http cookies (can’t add here due to long string)

getClass

resObj.getClass()

class io.restassured.internal.RestAssuredResponseImpl

 Till this we got to know how to get status code and other details of the response. Now we will see how to read the JSON response as per our test case validations for expected and actuals.

 From the response JOSN I want to read “name” field value to check I will be using this code

System.out.println(resObj.jsonPath().get("name"));

 Output: [Bhutan, India, Zimbabwe]

 Here system find and list out all the fields value which field name as “name” and gives array of values. So if I want to read only specific or as per occurrence, then below code helps.

System.out.println(resObj.jsonPath().get("name[0]"));

 Output: Bhutan

System.out.println(resObj.jsonPath().get("name[1]"));

 Output: India

System.out.println(resObj.jsonPath().get("name[2]"));

 Output: Zimbabwe

 One more scenario is what if I don’t know the at which occurrence my expected values comes, so for that what we need to do is read and split the array by “,” and loop till we find our expected result.    

String strFieldValues = resObj.jsonPath().get("name").toString().replace("[","").replace("]","");


String strFieldValue[] = strFieldValues.split(",");

boolean temp = false;

for(int i = 0;i<=strFieldValue.length-1;i++) {                  

    if(strFieldValue[i].trim().equalsIgnoreCase("India".trim())) {

         System.out.println("PASS");

         temp = true;

         break;

    }

    if((!temp) && i == strFieldValue.length-1) {

        System.out.println("FAIL");

    }

}


Code Explanation:

 Here we are reading the values from the field name called “name”, since its coming as array we are converting it into string and replacing the extra square braces. This value storing it in “strFieldValues” variable.

 Once we got the value as string we are splitting string array into each single value using split(“,”) method and using “,” can condition to split. After that looping till, we get our expected value.

 Considering another scenario and want to validate language code, below code will be used.

String strFieldValues = resObj.jsonPath().get("languages.name").toString().replace("[","").replace("]","");


String strFieldValue[] = strFieldValues.split(",");

boolean temp = false;

for(int i = 0;i<=strFieldValue.length-1;i++) {                  

    if(strFieldValue[i].trim().equalsIgnoreCase("Hindi".trim())) {

        System.out.println("PASS");

        temp = true;

        break;

     }

    if((!temp) && i == strFieldValue.length-1) {

        System.out.println("FAIL");

    }

}


 We can parameterize the whole scenario by reading input and output from external source like excel, that I will be covering in next post.




                         That’s all Folks.