Python API Automation Testing Suite with requests, pytest, and pytest‑html

This guide demonstrates how to build a Python API automation testing suite using requests, pytest, and pytest‑html, covering environment setup, project structure, common utilities, test case implementation, advanced assertions, error handling, test data management, and HTML report generation.

Test Development Learning Exchange
Test Development Learning Exchange
Test Development Learning Exchange
Python API Automation Testing Suite with requests, pytest, and pytest‑html

In Python, the requests library can be used for API automation testing, and testing frameworks such as unittest or pytest can organize and run test suites.

Installation pip install requests pytest Project directory structure

project/</code>
<code>│</code>
<code>├── common/           # public methods module</code>
<code>│   └── utils.py      # request, assertion utilities</code>
<code>├── conf/             # configuration module</code>
<code>│   └── config.py     # environment and base URL</code>
<code>├── data/             # test data module</code>
<code>│   └── test_data.json # input data for test cases</code>
<code>├── log/              # log module</code>
<code>│   └── log.txt       # runtime logs</code>
<code>├── report/           # report module</code>
<code>│   └── report.html   # generated HTML report</code>
<code>├── test_case/        # test case modules</code>
<code>│   ├── test_login.py # login API tests</code>
<code>│   ├── test_signup.py# signup API tests</code>
<code>│   └── ...           # other API tests</code>
<code>└── testsuite.py      # test suite runner

common/utils.py – common functions

import requests</code>
<code>import json</code>
<code>def send_request(method, url, headers=None, params=None, data=None):</code>
<code>    response = requests.request(method, url, headers=headers, params=params, data=data)</code>
<code>    response.raise_for_status()  # raise if status not 200</code>
<code>    return response.json()</code>
<code>def assert_response(response_data, expected_key, expected_value):</code>
<code>    assert expected_key in response_data, f"Expected key '{expected_key}' not found in response."</code>
<code>    assert response_data[expected_key] == expected_value, f"Expected value for '{expected_key}' is '{expected_value}', but got '{response_data[expected_key]}'"

conf/config.py – configuration

TEST_ENVIRONMENT = "development"</code>
<code>BASE_URL = "http://localhost:8000/api/"

test_case/test_login.py – example test case

import json</code>
<code>from project.common.utils import send_request, assert_response</code>
<code>from project.conf.config import BASE_URL</code>
<code>class TestLogin:</code>
<code>    def test_successful_login(self):</code>
<code>        url = f"{BASE_URL}login"</code>
<code>        data = {"username": "test_user", "password": "test_password"}</code>
<code>        response_data = send_request("POST", url, data=json.dumps(data))</code>
<code>        assert_response(response_data, "status", "success")</code>
<code>        assert_response(response_data, "message", "Logged in successfully.")</code>
<code>    def test_invalid_credentials(self):</code>
<code>        url = f"{BASE_URL}login"</code>
<code>        data = {"username": "invalid_user", "password": "invalid_password"}</code>
<code>        response_data = send_request("POST", url, data=json.dumps(data))</code>
<code>        assert_response(response_data, "status", "error")</code>
<code>        assert_response(response_data, "message", "Invalid credentials.")

testsuite.py – organize and run test cases

import pytest</code>
<code>from project.test_case import test_login, test_signup  # other test modules</code>
<code>@pytest.mark.parametrize("test_case_module", [test_login, test_signup])</code>
<code>def test_suite(test_case_module):</code>
<code>    suite = unittest.TestLoader().loadTestsFromModule(test_case_module)</code>
<code>    runner = unittest.TextTestRunner()</code>
<code>    results = runner.run(suite)</code>
<code>    assert results.wasSuccessful(), "Test suite failed."</code>
<code>if __name__ == "__main__":</code>
<code>    pytest.main(["--html=report/report.html", "--self-contained-html"])

Run the suite with: pytest testsuite.py Advanced assertions

def assert_in_response(response_data, key, expected_values):</code>
<code>    assert key in response_data, f"Expected key '{key}' not found in response."</code>
<code>    assert response_data[key] in expected_values, f"Expected value for '{key}' to be one of {expected_values}, but got '{response_data[key]}'"

Error handling in send_request

def send_request(method, url, headers=None, params=None, data=None):</code>
<code>    try:</code>
<code>        response = requests.request(method, url, headers=headers, params=params, data=data)</code>
<code>        response.raise_for_status()</code>
<code>        return response.json()</code>
<code>    except requests.exceptions.HTTPError as http_error:</code>
<code>        logging.error(f"HTTP error occurred: {http_error}")</code>
<code>        raise http_error</code>
<code>    except Exception as e:</code>
<code>        logging.error(f"Unexpected error occurred: {e}")</code>
<code>        raise e

Test data management

# data/test_data.py</code>
<code>LOGIN_TEST_DATA = {</code>
<code>    "valid_credentials": {"username": "test_user", "password": "test_password"},</code>
<code>    "invalid_credentials": {"username": "invalid_user", "password": "invalid_password"}</code>
<code>}

Use the data in test cases:

from project.data.test_data import LOGIN_TEST_DATA</code>
<code>class TestLogin:</code>
<code>    def test_successful_login(self):</code>
<code>        url = f"{BASE_URL}login"</code>
<code>        data = LOGIN_TEST_DATA["valid_credentials"]</code>
<code>        response_data = send_request("POST", url, data=json.dumps(data))</code>
<code>        assert_response(response_data, "status", "success")</code>
<code>        assert_response(response_data, "message", "Logged in successfully.")</code>
<code>    def test_invalid_credentials(self):</code>
<code>        url = f"{BASE_URL}login"</code>
<code>        data = LOGIN_TEST_DATA["invalid_credentials"]</code>
<code>        response_data = send_request("POST", url, data=json.dumps(data))</code>
<code>        assert_response(response_data, "status", "error")</code>
<code>        assert_response(response_data, "message", "Invalid credentials.")

Report generation with pytest-html pip install pytest-html Configure in testsuite.py:

import pytest</code>
<code>from pytest_html_reporter import attach_extra_css, add_context</code>
<code>@pytest.mark.parametrize("test_case_module", [test_login, test_signup])</code>
<code>def test_suite(test_case_module):</code>
<code>    # ... run tests ...</code>
<code>if __name__ == "__main__":</code>
<code>    pytest.main(["--html=report/report.html", "--self-contained-html"])</code>
<code>    attach_extra_css("custom.css")</code>
<code>    add_context({"project_name": "My API Test Project"})

Running the suite generates a report.html file with the test results.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

PythonAPI testingrequestspytesttest suite
Test Development Learning Exchange
Written by

Test Development Learning Exchange

Test Development Learning Exchange

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.