Encapsulating Custom Assertions for API Automation Testing
This article explains why custom assertion logic is needed in API automation testing, shows how to build a reusable Assertions class with methods for status code, JSON schema, key, JSONPath, and response time checks, and provides complete Python code examples for each use case.
In API automation testing, assertions verify that the response meets expectations; wrapping custom assertion logic improves readability, maintainability, and reduces code duplication.
1. Necessity of custom assertions – Encapsulating repeated assert statements into reusable methods reduces duplication, eases maintenance when logic changes, and makes test cases clearer.
2. Implementing the Assertions class
(a) Install the required jsonschema library:
pip install jsonschema(b) Create assertions.py and define the Assertions class with static methods:
import jsonschema
from jsonschema import validate
class Assertions:
@staticmethod
def assert_status_code(response, expected_status_code):
"""Validate that the response status code matches the expected value."""
assert response.status_code == expected_status_code, f"Status code mismatch. Expected: {expected_status_code}, Actual: {response.status_code}"
@staticmethod
def assert_json(response, schema):
"""Validate that the response JSON conforms to the given schema."""
try:
validate(instance=response.json(), schema=schema)
except jsonschema.exceptions.ValidationError as e:
raise AssertionError(f"JSON validation failed: {e}")
@staticmethod
def assert_json_key(response, key, expected_value):
"""Validate that a specific key in the JSON response has the expected value."""
data = response.json()
assert key in data, f"Key '{key}' not found in JSON data"
assert data[key] == expected_value, f"Key '{key}' value mismatch. Expected: {expected_value}, Actual: {data[key]}"
@staticmethod
def assert_json_path(response, json_path, expected_value):
"""Validate that a JSONPath expression in the response matches the expected value."""
from jsonpath_ng import jsonpath, parse
data = response.json()
json_expr = parse(json_path)
match = json_expr.find(data)
assert match, f"Path '{json_path}' not found"
assert match[0].value == expected_value, f"Path '{json_path}' value mismatch. Expected: {expected_value}, Actual: {match[0].value}"
@staticmethod
def assert_response_time(response, max_time):
"""Validate that the response time does not exceed the specified maximum (seconds)."""
assert response.elapsed.total_seconds() <= max_time, f"Response time exceeded. Max: {max_time}s, Actual: {response.elapsed.total_seconds()}s"3. Using the custom Assertions class
Example for status code verification:
import requests
from assertions import Assertions
def test_get_user_info():
response = requests.get("https://api.example.com/users/123")
Assertions.assert_status_code(response, 200)Example for JSON schema validation:
import requests
from assertions import Assertions
user_schema = {
"type": "object",
"properties": {
"id": {"type": "integer"},
"name": {"type": "string"},
"email": {"type": "string"}
},
"required": ["id", "name", "email"]
}
def test_get_user_info():
response = requests.get("https://api.example.com/users/123")
Assertions.assert_status_code(response, 200)
Assertions.assert_json(response, user_schema)Example for key value verification:
import requests
from assertions import Assertions
def test_get_user_info():
response = requests.get("https://api.example.com/users/123")
Assertions.assert_status_code(response, 200)
Assertions.assert_json_key(response, "name", "John Doe")Example for JSONPath value verification:
import requests
from assertions import Assertions
def test_get_user_info():
response = requests.get("https://api.example.com/users/123")
Assertions.assert_status_code(response, 200)
Assertions.assert_json_path(response, "$.name", "John Doe")Example for response time verification:
import requests
from assertions import Assertions
def test_get_user_info():
response = requests.get("https://api.example.com/users/123")
Assertions.assert_status_code(response, 200)
Assertions.assert_response_time(response, 2) # max 2 seconds4. Conclusion – By encapsulating custom assertion logic, test code becomes more reusable and maintainable; the article covered status code, JSON schema, key, JSONPath, and response time assertions with full Python examples.
Test Development Learning Exchange
Test Development Learning Exchange
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.