Image for post
Image for post

In this tutorial series, we will be learning Web Automation using Python and SeleniumBase framework. We will be covering everything from setting up your project from scratch to all the way to integrate it with CI/CD.

🤖 What is SeleniumBase?

SeleniumBase is a web automation framework built with Python, pytest, and Webdriver. Since it’s an entire framework it comes with some great in-built features such as –

  • All the capabilities of pytest, unittest, and nose for test discovery and running

Image for post
Image for post

In this tutorial series, we will be learning about Postman and how to do API testing as well as API test automation using Postman.

What is Postman?

A lot of people think of Postman as just an API client that allows you to send HTTP requests. While that is possible and you can send REST, SOAP & GraphQL requests directly from Postman but Postman is not just limited to that, it is packed with a lot more features such as:

  • Creating automated tests for your APIs in Postman which you can integrate with CI/CD pipeline

Image for post
Image for post

In this post, we’ll take a look at how to integrate API tests with Jenkins as well as add JUnit reporting with it.

Installation / Setup

  • You can check out this video to install Jenkins locally

Setup Test Job

  • Create a new freestyle test job
npm install // to install all the packages
npm test // to run your tests
  • In the post-build step, choose the JUnit report option and add your report path, example — test*.xml

Image for post
Image for post

In this post, we’ll take a look at how to get reporting setup for API tests. So far we have been printing results out on the console, now we’ll take a look at how to generate HTML report using mochawesome reporter.


Add mochawesome to the project:

npm install --save-dev mochawesome

Run the tests

To run the tests, you can simply pass them with the mocha command:

mocha test.js --reporter mochawesome

This will generate a mochawesome-report/ directory in your root folder which will contain a mochawesome.html file. Open the file to see the results, which will look similar to this:

Image for post
Image for post

In this post, we’ll take a look at some other ways to optimize our test. We will create a new config file to store configuration related data as well as use faker.js to randomize test data.

Configuration file

Instead of storing URLs and other configuration related within our tests file, we can create a config file and store data there and import it directly in our tests. This will help clean up our tests and make it easier to read. Even something as simple as this works:

export default {
baseUrl: '',
// ... other config data

Randomizing test data

Instead of hardcoding test data, we can use external libraries such as faker.js to help generate random test data for us. To use faker, import the package using npm install faker and then start using it…

Image for post
Image for post

So far we have written all the positive/happy path test scenarios, in this post, we’ll take a look at how we can write a few negative API tests to ensure our APIs are secure and functioning as they should.

Let’s take a look at some examples -

Unauthenticated Test
Create a test to ensure the user cannot hit the APIs without being properly authenticated.

it('401 Authentication Failed', async () => {
// sending request without the Authentication Token
const postRes = await'posts').send(data);
expect('Authentication failed');

Validation Failed
Create a test to ensure the user should not be able to create data without passing in the required fields. …

Image for post
Image for post

In this post, I will cover how async-awaits can help us write better and clean tests. async-await makes working with asynchronous programming a bit easier for us, let's see how it works -


async functions and await keywords were introduced in ECMAScript 2017 edition. When you pass a async keyword to a function, it returns a promise. And, the await keyword waits for the promise to be fulfilled before moving on to the next step.

So how does it relate to our API tests? Well, let’s take a look at an example. We’ll write a test to create a user post, this test will first create a user and then use the userId to create a post. …

Image for post
Image for post

So far in the previous posts, we wrote a few API tests for various HTTP methods and we were relying on the data that already existed on our test site. The challenge with that is if the existing data changes or gets removed it’ll end up breaking our tests. Let’s take a look at how we can fix that.

Current test structure

This is how the tests have been structured so far:

// GET Tests - uses existing userId to get the user data
// POST Test - creates a new user
// PUT Test - uses existing userId to update the user data
// DELETE Test - uses existing userId to delete the user…

Image for post
Image for post

The HTTP DELETE method is pretty straightforward, it deletes an existing resource and if the resource is already deleted it will most likely throw a ‘not found’ error.

Let’s take a look at an example -

it('DELETE /users/:id', () => {
return request
.set('Authorization', `Bearer ${TOKEN}`)
.then((res) => {

This will likely return the body similar to this-

{ code: 204, meta: null, data: null }

And, upon hitting the same request again, you will see a not-found error -

{ code: 404, meta: null, data: { message: 'Resource not found' } }

Check out this video to see a detailed explanation of how to work with the HTTP DELETE method:

You can also clone the GitHub repo to access this…

Image for post
Image for post

Similar to the HTTP POST method, the HTTP PUT method also takes in the request payload but instead of creating a new resource, it lets the user update the existing resource.

The difference between the PUT and POST method is that PUT is idempotent i.e you can keep calling the same request multiple times but it won't have any side effects, unlike a POST request.

Let’s take a look at an example of a PUT request below -

it('PUT /users/:id', () => {
// data to update
const data = {
status: 'Active',
name: `Luffy - ${Math.floor(Math.random() * 9999)}`,
return request
.set('Authorization', `Bearer ${TOKEN}`)
.then((res) => {
expect(; …


Automation Bro

I enjoy discussing topics related to Test Automation | Quality Assurance | Web Dev. Check out my Youtube channel — AutomationBro

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store