RestAssured – API Automation & Building Cucumber Framework
- Quality Engineering
- Selenium
- WebDriver
RestAssured – API Automation & Building Cucumber Framework
API automation refers to the process of automating the testing, deployment, and management of Application Programming Interfaces (APIs). APIs allow different software systems to communicate and interact with each other. API automation involves using automated tools and scripts to perform tasks related to API testing, monitoring, and integration.
Key aspects of API automation include:
- Testing Automation:
- Functional Testing: Automated tests are created to verify that the API functions as expected. This involves testing various inputs, outputs, and scenarios to ensure the API behaves correctly.
- Regression Testing: Automated tests are run to ensure that changes or updates to the API do not negatively impact existing functionalities.
- Performance Testing: Automated tools can simulate high loads and stress conditions to assess the API’s performance and scalability.
Practice APIs : Import these curl into postman which we going to automate.
Get Request:
curl –location ‘https://jsonplaceholder.typicode.com/posts/1’
Post Request:
curl –location ‘https://jsonplaceholder.typicode.com/posts’ \
–header ‘Content-Type: application/json’ \
–data ‘{“userId”: 1, “title”: “New Post”, “body”: “This is the body of the new post.”}’
Put Request:
curl –location –request PUT ‘https://jsonplaceholder.typicode.com/posts/1’ \
–header ‘Content-Type: application/json’ \
–data ‘{“id”: 1, “title”: “Updated Post”, “body”: “This is the updated body of the post.”}’
Patch Curl :
curl –location –request PATCH ‘https://jsonplaceholder.typicode.com/posts/1’ \
–header ‘Content-Type: application/json’ \
–data ‘{“body”: “This is a partial update of the body.”}’
Delete Curl :
curl –location –request DELETE ‘https://jsonplaceholder.typicode.com/posts/1‘
Create Project Structure : Use any IDE to create a blank Maven project, Intellij IDEA or Eclipse.
Create Packages as below
- cucumber.Options
- features
- pojo [ It can be skipped as of now we’ll be using string format for payloads ]
- resources
- stepDefinations
Let’s Automate
Add Dependencies to pom.xml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 |
<?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>org.example</groupId> <artifactId>ApiFrameW</artifactId> <version>1.0-SNAPSHOT</version> <properties> <maven.compiler.source>17</maven.compiler.source> <maven.compiler.target>17</maven.compiler.target> </properties> <build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-surefire-plugin</artifactId> <configuration> <testFailureIgnore>true</testFailureIgnore> </configuration> </plugin> <plugin> <groupId>net.masterthought</groupId> <artifactId>maven-cucumber-reporting</artifactId> <version>5.0.0</version> <executions> <execution> <id>execution</id> <phase>verify</phase> <goals> <goal>generate</goal> </goals> <configuration> <projectName>cucumber-jvm-example</projectName> <!-- optional, per documentation set this to "true" to bypass generation of Cucumber Reports entirely, defaults to false if not specified --> <skip>false</skip> <!-- output directory for the generated report --> <outputDirectory>${project.build.directory}</outputDirectory> <!-- optional, defaults to outputDirectory if not specified --> <inputDirectory>${project.build.directory}/jsonReports</inputDirectory> <jsonFiles> <!-- supports wildcard or name pattern --> <param>**/*.json</param> </jsonFiles> <!-- optional, set true to group features by its Ids --> <mergeFeaturesById>false</mergeFeaturesById> <!-- optional, set true to get a final report with latest results of the same test from different test runs --> <mergeFeaturesWithRetest>false</mergeFeaturesWithRetest> <!-- optional, set true to fail build on test failures --> <checkBuildResult>false</checkBuildResult> </configuration> </execution> </executions> </plugin> </plugins> </build> <dependencies> <!-- https://mvnrepository.com/artifact/io.cucumber/cucumber-java --> <dependency> <groupId>io.cucumber</groupId> <artifactId>cucumber-java</artifactId> <version>7.12.1</version> </dependency> <!-- https://mvnrepository.com/artifact/io.cucumber/cucumber-junit --> <dependency> <groupId>io.cucumber</groupId> <artifactId>cucumber-junit</artifactId> <version>7.12.1</version> <scope>test</scope> </dependency> <!-- https://mvnrepository.com/artifact/io.rest-assured/rest-assured --> <!-- https://mvnrepository.com/artifact/io.rest-assured/rest-assured --> <dependency> <groupId>io.rest-assured</groupId> <artifactId>rest-assured</artifactId> <version>5.3.0</version> <scope>test</scope> </dependency> <!-- https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-databind --> <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-databind</artifactId> <version>2.15.2</version> </dependency> <!-- https://mvnrepository.com/artifact/junit/junit --> <!-- https://mvnrepository.com/artifact/junit/junit --> <!-- https://mvnrepository.com/artifact/junit/junit --> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.12</version> <scope>test</scope> </dependency> </dependencies> </project> |
- Now Create one gloabal.properties file under resources package and place BaseUrl: global.properties
1 |
baseUrl=https://jsonplaceholder.typicode.com |
2. Get end point and put it in APIresources Enum file: APIresources.java
1 2 3 4 5 6 7 8 9 10 11 12 13 |
package resources; public enum APIresources { createblogAPI("/posts"); private String resource; APIresources(String resource) { this.resource= resource; } public String getResource(){ return resource; } } |
Note : Given constant name “createblogAPI” should be called in Feature file. It’s a Enum class.
An enum is a special “class” that represents a group of constants (unchangeable variables, like final variables). To create an enum , use the enum keyword (instead of class or interface), and separate the constants with a comma.
Utils/BaseSteps : utils.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 |
package resources; import io.restassured.builder.RequestSpecBuilder; import io.restassured.filter.log.RequestLoggingFilter; import io.restassured.filter.log.ResponseLoggingFilter; import io.restassured.http.ContentType; import io.restassured.path.json.JsonPath; import io.restassured.response.Response; import io.restassured.specification.RequestSpecification; import java.io.*; import java.util.Properties; public class utils { public static RequestSpecification req; public RequestSpecification requestspecification() throws IOException { if(req==null) { PrintStream log = new PrintStream(new FileOutputStream("logging.txt")); req = new RequestSpecBuilder().setBaseUri(getglobalvalues("baseUrl")).addQueryParam("key", "qaclick123") .addFilter(RequestLoggingFilter.logRequestTo(log)) .addFilter(ResponseLoggingFilter.logResponseTo(log)) .setContentType(ContentType.JSON).build(); return req; } return req; } public static String getglobalvalues(String key) throws IOException { Properties prop = new Properties(); FileInputStream fis = new FileInputStream("D:\\APITraining\\src\\test\\java\\resources\\global.properties"); prop.load(fis); return prop.getProperty(key); } public String getJsonPath(Response response, String key) { String resp=response.asString(); JsonPath js = new JsonPath(resp); return js.get(key).toString(); } } |
FeatureFile : AddBlog.feature
Now need to setup feature file : there are few syntax we need to follow
- At the top of this we will define”Feature: ” Keyword
- Then we will define Scenario / Scenario outline ( if multiple inputs )
- Scenario Outline : Verify Blog added successfully
- Then Follow given, when, then
1 2 3 4 5 6 7 8 9 10 11 12 |
Feature: Blog Test Scenario Outline : Verify Blog added successfully Given create blog api payload with "<id>" "<title>" "<body>" When user calls "createblogAPI" with "post" http method Then check api response is 201 And "title" in response body "My Post" And "message" in response body "successful" Examples: | id | title | body | | 1 | My Post | This is the body of the new post. | |
So let suppose in next case we need to validate “message” is “successful” then we will only put these values in last line in new case
i.e. And “message” in response body “successful”
StepDefination File :
Now need to set up a step definition file and all our java code will be there. It supports “Gherkin” syntax so to achieve this we can run our feature file once and in error response we can get it. Carefully copy all the steps from undefined steps : And paste to step definition file.
Now extend utils class here where we defined and setup our base url, loggings : stepDefinations.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 |
package stepDefinations; import io.cucumber.java.en.Given; import io.cucumber.java.en.Then; import io.cucumber.java.en.When; import io.restassured.response.Response; import io.restassured.specification.RequestSpecification; import org.junit.Assert; import resources.APIresources; import resources.TestDatabuild; import resources.utils; import java.io.IOException; import static io.restassured.RestAssured.given; import static org.junit.Assert.assertEquals; public class stepDefination extends utils { RequestSpecification res; Response response; TestDatabuild data = new TestDatabuild(); @Given("create blog api payload with {string} {string} {string}") public void create_blog_api_payload_with(String id, String title, String body) throws IOException { // Write code here that turns the phrase above into concrete actions res = given().spec(requestspecification()).body(data.createblogmethod(id, title, body)); } @When("user calls {string} with {string} http method") public void user_calls_with_http_method(String resource, String method) { // Write code here that turns the phrase above into concrete actions APIresources Endpoint = APIresources.valueOf(resource); if(method.equalsIgnoreCase("post")){ response = res.when().post(Endpoint.getResource()); } else if(method.equalsIgnoreCase("get")){ response=res.when().get(Endpoint.getResource()); } else if(method.equalsIgnoreCase("delete")){ response = res.when().delete(Endpoint.getResource()); } else if(method.equalsIgnoreCase("put")){ response = res.when().put(Endpoint.getResource()); } } @Then("check api response is {int}") public void check_api_resonse_is(Integer int1) { // Write code here that turns the phrase above into concrete actions Assert.assertEquals(response.getStatusCode(),201); } @Then("{string} in response body {string}") public void in_response_body(String key, String value) { // Write code here that turns the phrase above into concrete actions assertEquals(getJsonPath(response,key),value); } } |
Method 1 :
Here we will be setting up a dynamic payload ( API body ) and base url Convert Json to string first and place it in “TestDatabuild” file We can use this website https://jsontostring.com/ to convert json to string.
But here our pay load is dynamic lets place variable here carefully between “+variable+”
Create a new file : TestDatabuild.java
1 2 3 4 5 6 7 8 9 |
package resources; public class TestDatabuild { public String createblogmethod (String id, String title, String body){ return "{\"userId\":"+id+",\"title\":\""+title+"\",\"body\":\""+body+".\"}"; } } |
Explanation :
Move to next Method : It is dynamically setting up request type
Move to next method : These are only for validation purpose
1 2 3 4 5 6 7 8 9 |
@Then("check api response is {int}") public void check_api_resonse_is(Integer int1) { // Write code here that turns the phrase above into concrete actions Assert.assertEquals(response.getStatusCode(),201); } @Then("{string} in response body {string}") public void in_response_body(String key, String value) { // Write code here that turns the phrase above into concrete actions assertEquals(getJsonPath(response,key),value); |
Next create test runner file and give annotation and path to feature and step def file : Testrunner.java
1 2 3 4 5 6 7 8 9 10 11 12 13 |
package cucumber.Options; import io.cucumber.junit.Cucumber; import io.cucumber.junit.CucumberOptions; import org.junit.runner.RunWith; @RunWith(Cucumber.class) @CucumberOptions(features = {"src/test/java/features"},plugin ="json:target/jsonReports/cucumber-report.json", glue={"stepDefinations"} , tags= "@regression" ) public class Testrunner { } |
Run Test Runner File :
I hope you enjoyed this informative blog. Feel free to ask any questions or queries in comments or Join on linkedIn.
Related content
Auriga: Leveling Up for Enterprise Growth!
Auriga’s journey began in 2010 crafting products for India’s