With more and more applications now relying on a REST API endpoint , it has become important and necessary to thoroughly test your API endpoints.
Gone are the days when developers and testers could simple do away with manually testing API’s using tools like Postman (which can now be used for automation as well) or Advanced Rest Client. Now a days, knowing how to automate a suite of API’s using some tools like Rest Assured, Chakram is considered to be a vital part of the QA cycle, and a much needed skill for the QA community.
Today, I’m going to give a sample tutorial on one of these API testing tools. SuperTest.
Supertest is library written to test HTTP calls in node.js. So if you want to write test cases which going to do some HTTP calls ( GET, POST, PUT etc ) then this might be the useful tool for you.
We’re going to use Supertest
, Mocha
, chai
for the tests. The API end points can be found on this amazing website https://reqres.in
If you’re not familiar with mocha
and chai
, I suggest you read first before going in to use these test cases and API automation tool supertest
.
Installation
For this purpose I’ve created a sample directory – if you’re using a Mac
or Linux
, you can use the mkdir directory_name
and then use the cd
command to go inside the directory just created.
Inside the directory, use npm init
to get started with setting up the project.
Once done , use the npm i
or npm install
command to install supertest
, mocha
, chai
and mochawesome
, which we will use for reporting purposes.
Now inside the root of the directory, create a new folder called test
. Here we’re going to keep all the .js
files that we’re going to use for tests.
GET REQUEST
Head over to https://reqres.in
to get a sample GET
endpoint for use. We’ll be using the following endpoint
https://reqres.in/api/users?page=2
which outputs a sample response of this type
{ "page": 2, "per_page": 3, "total": 12, "total_pages": 4, "data": [ { "id": 4, "first_name": "Eve", "last_name": "Holt", "avatar": "https://s3.amazonaws.com/uifaces/faces/twitter/marcoramires/128.jpg" }, { "id": 5, "first_name": "Charles", "last_name": "Morris", "avatar": "https://s3.amazonaws.com/uifaces/faces/twitter/stephenmoon/128.jpg" }, { "id": 6, "first_name": "Tracey", "last_name": "Ramos", "avatar": "https://s3.amazonaws.com/uifaces/faces/twitter/bigmancho/128.jpg" } ] }
Now copy paste this code in a new file – let it be list_users.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const supertest = require('supertest'); | |
const expect = require('chai').expect; | |
const schema = require('../validation/list_users_schema'); | |
const joi = require('joi'); | |
let baseURL = supertest("https://reqres.in"); | |
let list_users = "/api/users?page=2"; | |
describe('First Request to Get Users',()=>{ | |
let res; | |
it("See Response", async function () { | |
res = await baseURL.get(list_users); //Sending the GET request | |
console.log(res.body); | |
}); | |
it('checks that the response was OK',async()=>{ | |
await (expect(res.status).to.equal(200)); | |
}); | |
it('asserts the various attributes',async ()=>{ | |
await(expect(res.body.page).to.equal(2)); | |
}); | |
it('checks that the data is an array',async ()=>{ | |
await (expect(res.body.data).to.be.an('array')); | |
}); | |
it('prints length of data array',async()=>{ | |
await (console.log(res.body.data.length)); | |
}); | |
it('gets the id from the array',async()=>{ | |
for(let i=0;i<res.body.data.length;i++){ | |
await(console.log(res.body.data[i].id)); | |
await (console.log(res.body.data[i].first_name)); | |
} | |
}); | |
it('matches the schema for the API',async()=>{ | |
await (expect(joi.validate(schema.schema).error).to.be.null); | |
}) | |
}); |
Now, let’s dwell in this code and see what is happening. As you can see from the first few lines, we’re using the get
verb.
Now before running this test, head over to you package.json
file and add this in the test
command , under the scripts
flag
"test" : "mocha test --reporter mochawesome"
Your package.json
file should look like this
Now run this test from command prompt or use Ctrl + ~
to open the command prompt in Visual Studio Code itself – and do
npm test
and see the output
We’re using a couple of simple assertions like the status code is 200
, and checking values of a couple of attributes like page
value to equal 2.
Another assertion is that the data
key inside the main response body is an array
. And a couple of other assertions that length of array is something.
The last assertion is something different. Let’s talk about it in detail.
tl:dr; this assertion is validating that the API response matches a given schema for the API. In order to do that we have used the joi
package from npm
.
Start by installing joi
from the npm
repository using
npm i joi
Now we create a new directory inside the root directory of the folder that we’ve created for our tests. Let’s call it validation
. Inside this folder, create a new file called list_users_schema.js
where we’re going to put the schema file for the GET
request API.
Now, let’s look at the schema of the API.
We have an JSON
object, which contains a number of entries, like page
, per_page
, and an array of objects data
, which we asserted above to be an array.
To define the schema, let’s have this code pasted.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const joi = require('joi'); | |
module.exports = { | |
schema : joi.object().keys({ | |
page : joi.number().integer().required(), | |
per_page: joi.number().integer().required(), | |
total : joi.number().integer().required(), | |
total_pages: joi.number().integer().required(), | |
data : joi.array().items(joi.object({ | |
id: joi.number().integer().required(), | |
first_name : joi.string().required(), | |
last_name : joi.string().required(), | |
avatar : joi.string().uri().required() | |
})) | |
}) | |
} |
Here, we’re defining the corresponding enteries and their types – we can add a whole range of checks for the API schema. Head over to the github link of joi to learn more and how we can add schema checks for JSON
objects or JSON
arrays.
Once we have the schema, we call it in the list_users.js
file at the top and then apply the assertion that there is no error when checking the schema.
POST REQUEST
Head over to https://reqres.in
to get a sample POST
endpoint for use. We’ll be using the following endpoint
Let’s create a new file called create_user.js
inside the test
folder and copy paste this code
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const supertest = require('supertest'); | |
const expect = require('chai').expect; | |
const schema = require('../validation/list_users_schema'); | |
const joi = require('joi'); | |
let baseURL = supertest("https://reqres.in"); | |
let list_users = "/api/users"; | |
describe('POST Request',()=>{ | |
let post_resp; | |
it('makes a POST call ',async ()=>{ | |
post_resp = await baseURL.post(list_users) | |
.type('form') | |
.send({ | |
"name": "morpheus", | |
"job": "leader" | |
}) | |
.set('Accept','/application/\json/'); | |
await (console.log(post_resp.body)); | |
}); | |
it('asserts that the response code is 201',async ()=>{ | |
await (expect(post_resp.status).to.eql(201)); | |
}) | |
}); |
PS : In order to send a POST
call, for some reason, you need to add the type('form')
in the POST
call as evident from the syntax. I couldn’t find a reason for the same but this has been mentioned here.
Once done, save the file, head over to the terminal and again run the test using npm test
. If you only want this test to run , add a .only
in front of the it
block in the test like it.only('something')
and it will only run that test. The output comes like this
Let’s add an assertion that the status returned is 201 - Created
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const supertest = require('supertest'); | |
const expect = require('chai').expect; | |
const schema = require('../validation/list_users_schema'); | |
const joi = require('joi'); | |
let baseURL = supertest("https://reqres.in"); | |
let list_users = "/api/users"; | |
describe('POST Request',()=>{ | |
let post_resp; | |
it('makes a POST call ',async ()=>{ | |
post_resp = await baseURL.post(list_users) | |
.type('form') | |
.send({ | |
"name": "morpheus", | |
"job": "leader" | |
}) | |
.set('Accept','/application/\json/'); | |
await (console.log(post_resp.body)); | |
}); | |
it('asserts that the response code is 201',async ()=>{ | |
await (expect(post_resp.status).to.eql(201)); | |
}) | |
}); |
We can see that the assertion passes
Now, as you see we have both the GET
and POST
request automated with supertest
. You can now add any assertion that you want in the tests- be it about the size , type of output, status code etc.
All these tests have been combined in a nice github repository – https://github.com/zac11/supertest-demo
Clone this repository and cd
to go inside it and do npm install
to install the dependencies. Once done , do npm test
to run the test files
Go inside the root directory and locate a folder named mochawesome-report
and inside you’ll see the html
report. Open the report in any browser and you’ll see something like this –
Apart from GET
and POST
, the repository also contains a DELETE
verb and PUT
verb call to demonstrate how it can be done.
Please share and follow my blog for more such automation content.