API Testing with Playwright: Handbook for beginners

API Testing with Playwright: Handbook for beginners

When it comes to testing APIs, having efficient tools and frameworks is crucial. Playwright, a powerful automation library, not only excels in browser automation but also provides seamless API testing capabilities. In this article, we'll delve into how Playwright can be leveraged for API testing in Python.

Installation

To begin with, let's set up our testing environment. We'll need Python installed on our system along with the Playwright library. Playwright can be installed via pip, ensuring compatibility with various operating systems.

pip install pytest-playwright

Once Playwright is installed, we'll also need Pytest, a popular testing framework for Python.

pip install pytest

Understanding the Test Suite

Now that our environment is set up, let's take a closer look at the test suite we'll be writing. Our suite consists of test functions targeting different HTTP methods: GET, POST, PUT, and DELETE. These functions utilize the capabilities of the Playwright library to send requests and validate responses.

import os
from typing import Generator

import pytest
from playwright.sync_api import Playwright, APIRequestContext

__BASE_URL__ = "https://httpbin.dmuth.org/"

@pytest.fixture(scope="session")
def api_request(
    playwright: Playwright,
) -> Generator[APIRequestContext, None, None]:
    headers = {
        "Accept": "application/json",
        "User-Agent": "articles.eminmuhammadi.com",
    }
    request_context = playwright.request.new_context(
        base_url=__BASE_URL__, extra_http_headers=headers
    )
    yield request_context
    request_context.dispose()

The api_request fixture is responsible for creating a new API request context using Playwright. It sets the base URL for all requests and can include additional headers if needed. After yielding the request context to tests, it ensures proper disposal afterward.

def test_get(api_request: APIRequestContext) -> None:
    response = api_request.get("/get/args/?foo=bar")

    assert response.status == 200
    assert response.ok
    assert response.json()["foo"] == "bar"

This code block defines a test function named test_get that verifies the functionality of a GET request to a specific endpoint. The function takes an APIRequestContext object named api_request as a parameter, indicating that it's part of a test suite using pytest. Inside the function, a GET request is sent to the "/get" endpoint using the api_request object, which encapsulates the context for making HTTP requests.

def test_post(api_request: APIRequestContext) -> None:
    data = {
        "foo": "bar",
    }

    response = api_request.post("/post", data=data)

    assert response.status == 200
    assert response.ok
    assert response.json()["data"]["foo"] == "bar"

This code block defines a test function named test_post responsible for testing the functionality of a POST request to a specific endpoint. Within the function, a Python dictionary named data is defined, representing the payload to be sent along with the POST request. This payload typically contains key-value pairs of data that the API endpoint expects to receive. The api_request object, which encapsulates the context for making HTTP requests, is then used to send a POST request to the "/post" endpoint, including the defined data.

def test_put(api_request: APIRequestContext) -> None:
    data = {
        "foo": "bar",
    }

    response = api_request.put("/put", data=data)

    assert response.status == 200
    assert response.ok
    assert response.json()["data"]["foo"] == "bar"

This code block defines a test function named test_put, specifically designed to assess the functionality of a PUT request to a designated endpoint. Within this function, a Python dictionary named data is created, serving as the payload to be included in the PUT request. This payload typically contains the data to be updated or modified on the server side. The api_request object is then employed to dispatch a PUT request to the "/put" endpoint, incorporating the specified data.

def test_delete(api_request: APIRequestContext) -> None:
    response = api_request.delete("/delete")

    assert response.status == 200
    assert response.ok

This code block defines a test function named test_delete responsible for evaluating the behavior of a DELETE request to a specific endpoint. Within this function, the api_request object, which encapsulates the context for making HTTP requests, is utilized to dispatch a DELETE request to the "/delete" endpoint. This action is intended to remove or delete a resource from the server.

After the request is sent, two assertions are utilized to check the response: initially, it validates that the response's HTTP status code is 200, signifying a successful request, while subsequently ensuring that the response object meets the criteria of being "OK," typically denoted by a status code within the 200-299 range. These assertion procedures are pivotal in verifying the proper handling of GET, POST, PUT, DELETE requests by the API endpoint, thereby safeguarding the integrity and effectiveness of the API's deletion functionalities.

Results

To view test results using pytest-html, you can follow these steps

pip install pytest-html

Once installed, you can run pytest with the --html option followed by the desired filename for the HTML report

pytest --html=report.html

The HTML report provides a comprehensive overview of the test results, including the number of tests passed, failed, and skipped, along with any errors or failures encountered during testing. You can navigate through the report to view details of each test case, including the test name, status, duration, and any captured output or exceptions.

By following these steps, you can generate and view an HTML report of your test results using pytest-html, providing a more structured and visually appealing way to analyze the outcomes of your test suite.

Conclusion

In conclusion, testing APIs is essential in ensuring the reliability and functionality of web applications. With Playwright, developers have access to a versatile automation library that not only excels in browser automation but also provides seamless capabilities for API testing in Python.

By utilizing pytest-html, developers can generate comprehensive HTML reports of their test results. These reports offer detailed insights into the test outcomes, including the number of tests passed, failed, or skipped, along with any encountered errors or failures. This structured presentation facilitates easy analysis and debugging, ultimately contributing to the overall quality and reliability of the tested APIs.

In conclusion, leveraging Playwright for API testing in Python, coupled with pytest and pytest-html, provides developers with robust tools and frameworks to streamline the testing process, leading to more resilient and dependable web applications.