API Testing: Playwright and Python (Part 1)

Abhilash Sharma
5 min readApr 25, 2023

--

Playwright is a Node.js library for browser automation that was developed by Microsoft. It allows you to automate interactions with web applications in modern browsers such as Chromium, Firefox, and WebKit. Playwright provides a high-level API that is easy to use and supports multiple programming languages such as JavaScript, Python, and Java.

🍀 In addition to UI testing, Playwright can also be used to test APIs by making HTTP requests and validating responses.

Image Source: https://applitools.com/

In this blog we will write test scripts to automate a post call using Playwright & Pytest.

⭐️ Overview

  1. Setup Python Project using Pycharm
  2. Add Plawright & Pytest Dependencies
  3. API Modelling
  4. Write Test Scripts
  5. Execute Test Scripts
  6. Managing the Scripts Pythonistas Way (Part 2) 😃

Setup Python Project using Pycharm

  • Download the pycharm from above mentioned link & setup the python3 environment your machine.
  • Create a new project using a python3 virtual environment (venv)

The initial setup will look like this 👇

Add Plawright & Pytest Dependencies

Create a dependencies file on base level and following dependencies.

📁requirements.txt

pytest-playwright
pytest
playwright

💻 Run following command to install the dependencies. (preferably from pycharm console so dependencies will be install on the venv level)

pip install -r requirements.txt

API Modelling

Here we need to understand how playwright creates a service using an endpoint.

Before diving deep into the api modelling part we need to understand about APIRequestContext.

APIRequestContext: This is a class that represents an HTTP request context for making API requests. It provides a high-level API for making HTTP requests and retrieving responses in your API tests.

The APIRequestContext class is part of the Playwright network API and is used to intercept and modify HTTP requests and responses. It allows you to:

  • Modify the request headers and body
  • Add query parameters to the request URL
  • Mock server responses for testing
  • Measure request and response timings

✨ In pytest we will use the APIRequestContext instance as pytest fixture, which can be utilized further in the test scripts.

Let’s create our new python file to add these configuration.

🍀 Always add “test” prefix or suffix to your python file & test method names so that pytest can easily catch your scripts for test execution.

test_playwright_api.py

First import the required dependencies —

import pytest
from typing import Generator
from playwright.sync_api import Playwright, APIRequestContext

We will be using https://reqres.in demo apis for our test scripts.

Now configure the user service using APIRequestContext , for this we will create a pytest fixture with the session scope👇

This fixture returns a request context of type APIRequestContext , which can be further utilised to do CRUD operations.

@pytest.fixture(scope="session")
def user_api_request_context(playwright: Playwright) -> Generator[APIRequestContext, None, None]:
request_context = playwright.request.new_context(
base_url="https://reqres.in"
)
yield request_context
request_context.dispose()

Write Test Scripts

We will write 3 scripts to cover happy scenarios of POST call and GET call & 1 negative scenario for get call.

Here we will add one more fixture to add automatically generated user ids, so that these Ids can be further utilized in get calls.

@pytest.fixture(scope="session")
def user_ids():
ids = []
yield ids

✅ POST /api/users

In this test script method we are using user_api_request_context fixture to execute API calls and user_ids fixture to store the ids for futher validations.

def test_create_user(user_api_request_context: APIRequestContext, user_ids) -> None:
payload = {
"name": "Ramadheer Singh",
"job": "Rangdari"
}

response = user_api_request_context.post(url=f"/api/users", data=payload)
assert response.ok

json_response = response.json()
print("Create User API Response:\n{}".format(json_response))
assert json_response["name"] == payload.get("name")
user_ids.append(json_response["id"])

🚩 GET /api/users/{user_id} — User Not Found

def test_get_user_not_found(user_api_request_context: APIRequestContext, user_ids) -> None:
response = user_api_request_context.get(url=f"/api/users/{user_ids[0]}")
assert response.status == 404

json_response = response.json()
print("Get User API Response - User Not Found:\n{}".format(json_response))

✅ GET /api/users/{user_id} —Happy Flow

Here I’m using a valid userId — “2” to fetch the details.

def test_get_user_happy_flow(user_api_request_context: APIRequestContext) -> None:
response = user_api_request_context.get(url=f"/api/users/2")
assert response.status == 200

json_response = response.json()
print("Get User API Response - Happy Flow:\n{}".format(json_response))
assert json_response["data"]["id"] == 2

Final code/ script 👇

import pytest
from typing import Generator
from playwright.sync_api import Playwright, APIRequestContext


@pytest.fixture(scope="session")
def user_ids():
ids = []
yield ids


@pytest.fixture(scope="session")
def user_api_request_context(playwright: Playwright) -> Generator[APIRequestContext, None, None]:
request_context = playwright.request.new_context(
base_url="https://reqres.in"
)
yield request_context
request_context.dispose()


def test_create_user(user_api_request_context: APIRequestContext, user_ids) -> None:
payload = {
"name": "Ramadheer Singh",
"job": "Rangdari"
}

response = user_api_request_context.post(url=f"/api/users", data=payload)
assert response.ok

json_response = response.json()
print("Create User API Response:\n{}".format(json_response))
assert json_response["name"] == payload.get("name")
user_ids.append(json_response["id"])


def test_get_user_not_found(user_api_request_context: APIRequestContext, user_ids) -> None:
response = user_api_request_context.get(url=f"/api/users/{user_ids[0]}")
assert response.status == 404

json_response = response.json()
print("Get User API Response - User Not Found:\n{}".format(json_response))


def test_get_user_happy_flow(user_api_request_context: APIRequestContext) -> None:
response = user_api_request_context.get(url=f"/api/users/2")
assert response.status == 200

json_response = response.json()
print("Get User API Response - Happy Flow:\n{}".format(json_response))
assert json_response["data"]["id"] == 2

Execute Test Scripts

Simply run the below command in your terminal (preferably pycharm terminal only where dependencies are available under python3 venv)

pytest -s

Output 👇

================================================================================ test session starts ================================================================================
platform darwin -- Python 3.9.6, pytest-7.3.1, pluggy-1.0.0
rootdir: /Users/abhilashsharma/Documents/learning/playwright/api-testing-playwright
plugins: base-url-2.0.0, playwright-0.3.3
collected 3 items

test_playwright_api.py Create User API Response:
{'name': 'Ramadheer Singh', 'job': 'Rangdari', 'id': '164', 'createdAt': '2023-04-25T05:52:36.141Z'}
.Get User API Response - User Not Found:
{}
.Get User API Response - Happy Flow:
{'data': {'id': 2, 'email': 'janet.weaver@reqres.in', 'first_name': 'Janet', 'last_name': 'Weaver', 'avatar': 'https://reqres.in/img/faces/2-image.jpg'}, 'support': {'url': 'https://reqres.in/#support-heading', 'text': 'To keep ReqRes free, contributions towards server costs are appreciated!'}}
.

================================================================================= 3 passed in 1.47s =================================================================================

In the next part we will discuss more about managing the scripts and how to create a well maintained framework for the same.

Stay tuned.

Thanks

--

--