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.
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 runnercommon/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 eTest 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.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
