Building a Test Automation Framework using Cypress.io — Adding API Testing (Part 3)
Hola!
In Part-2 of this article series we added Cucumber BDD support to our Test Automation Framework. In this article we will build on top of this, and add native API testing support. Native? using only cypress and no external JS libraries. Promesa.
What is an API? and why test it?
API testing is a type of software testing that involves testing application programming interfaces (APIs) directly and as part of integration testing to determine if they meet expectations for functionality, reliability, performance, and security. Since APIs lack a GUI, API testing is performed at the message layer.
API testing is now considered critical for automating testing because APIs now serve as the primary interface to application logic and because GUI tests are difficult to maintain with the short release cycles and frequent changes commonly used with Agile software development and DevOps.[1]
API tests are fast, give high ROI, and simplify the validation of business logic, security, compliance, and other aspects of the application. In cases where the API is a public one, providing end-users programmatic access to our application or services, API tests effectively become end-to-end tests and should cover a complete user story.[2]
Now that we know the what and the why, Let's Begin!!
Writing an API Test case
As part of this article, we are gonna be using a free API endpoint from PokéAPI.
PokéAPI provides lots of free Pokémon data using simple REST APIs.
We are gonna be using following Endpoint:
https://pokeapi.co/api/v2/pokemon/{pokemon_name or id}
This endpoint provides data for a Pokémon by providing a name or index.
Let's create an API directory under /feature folder, to store our API tests.
And add a feature file name Pokemon_test.feature
Now add following steps for the BDD API test:
We are going to make an API request for Pokémon endpoint and then validate request response code, response data and cookies present in response.
Writing GLUE Code for API Test:
So far we had a single Glue Code file for holding our UI test step-definitions. Now before we add step definitions for API steps, it makes it to segregate things a bit.
We are gonna be adding API & UI folders under stepDefinitions directory and move commonSteps.js to UI folder as it contains UI test steps only. Now under API folder, add new step-definition file apiSteps.js like shown below:
Now we will add step-definition code in apiSteps.js for Given step
...
Given As a user I want to execute Pokemon GET api for Pokemon "pikachu"
...
Corresponding Glue code, which includes initializing Cy.request() :
Cy.request() is the utility which is used for making HTTP request in Cypress.
here, we are providing request argument as failOnStatusCode:false
which is true by default, so run steps even when request status code is other than 2XX or 3XX.
More arguments can be found at Cypress Docs.
Similarly we can write glue code for other steps:
Here we are validating request status code and in subsequent step response body:
...
Then('Verify response status code is {int}', (statusCode) => {
cy.get('@get_pokemon_data').should((response)=> {
expect(response.status).to.eq(statusCode);
})
});
Then('Verify response details for Pokemon {string}', (pokename) => {
cy.get('@get_pokemon_data').should((response)=> {
expect(response.body).to.have.property('abilities');
//Different ways of validating nested properties
//1st Way
expect(response.body).to.have.nested.property('forms[0].name',pokename);
//2nd Way
expect(response.body.forms[0]).to.have.property('name',pokename);
//3rd Way
const name = response.body.forms[0].name;
assert.equal(name, pokename);
expect(response).to.have.property('headers');
})
});
Now in order to run this, we can provide API test specific tags in --env TAGS, so that only API test is run:
npx cypress run --env TAGS="@API"
Here we can see only API test feature file was passing and the UI feature test file Test1.feature is in pending (meaning it wasn't run)
Adding negative API test case
So far we had been running a test where we give a valid Pokémon name in query param, now we will write a test case where we will provide invalid Pokémon name so that we will get a HTTP status code 404.
We are gonna be using same Endpoint:
https://pokeapi.co/api/v2/pokemon/{invalid_pokemon_name}
In our test case, we are gonna provide a Pokémon name which is invalid such as "doraemon"
Now in order to run both test cases we will once again run the following command:
npx cypress run --env TAGS="@API"
So in this article, we added 2 API test cases and validated them for Response code and response body (for positive test case) using only inbuilt Cypress utilities.
See you next time, when we will be adding some advance things to our Frameworks such as page object model, environment support and reports etc. So keep tuned in.
Adiós!
GitHub repo: https://github.com/far11ven/Cypress-TestFramework/tree/develop/Part 03