Response Validation¶
The validation module provides validators for checking HTTP responses against expected schemas, status codes, content types, and other criteria.
Overview¶
Response validation ensures your API responses conform to expectations:
Status Code Validation - Check response status codes
Content Type Validation - Verify Content-Type headers
JSON Schema Validation - Validate response bodies against schemas
OpenAPI Validation - Validate against OpenAPI specifications
Composite Validation - Combine multiple validators
Quick Start¶
Basic status code validation:
from pytest_routes import StatusCodeValidator, ValidationResult
validator = StatusCodeValidator(allowed_codes=[200, 201, 204])
result: ValidationResult = validator.validate(response, route)
if result.valid:
print("Response is valid!")
else:
print(f"Errors: {result.errors}")
Combine multiple validators:
from pytest_routes import (
CompositeValidator,
StatusCodeValidator,
ContentTypeValidator,
JsonSchemaValidator,
)
validator = CompositeValidator([
StatusCodeValidator([200, 201]),
ContentTypeValidator(["application/json"]),
JsonSchemaValidator(schema={"type": "object"}),
])
result = validator.validate(response, route)
Validator Hierarchy¶
ResponseValidator (Protocol)
|
+-- StatusCodeValidator
|
+-- ContentTypeValidator
|
+-- JsonSchemaValidator
|
+-- OpenAPIResponseValidator
|
+-- CompositeValidator (combines others)
API Reference¶
Core Types¶
ValidationResult¶
- class pytest_routes.validation.response.ValidationResult[source]¶
Bases:
objectResult of response validation.
- Variables:
valid – Whether the validation passed.
errors – List of validation error messages.
warnings – List of validation warning messages.
- Parameters:
The result of a validation operation.
Attributes
validBoolean indicating if validation passed
errorsList of error messages (empty if valid)
warningsList of warning messages (non-fatal issues)
Example
result = ValidationResult( valid=False, errors=["Status code 500 not in allowed codes"], warnings=["Response time exceeded 1s"], ) if not result.valid: for error in result.errors: print(f"ERROR: {error}")
ResponseValidator Protocol¶
- class pytest_routes.validation.response.ResponseValidator[source]¶
Bases:
ProtocolProtocol for response validation.
Response validators check that HTTP responses conform to expected schemas, status codes, content types, and other criteria.
Protocol that all validators must implement.
- validate(response, route)[source]¶
Validate a response against expected schema.
- Parameters:
- Return type:
- Returns:
ValidationResult indicating success or failure with details.
- __init__(*args, **kwargs)¶
Validators¶
StatusCodeValidator¶
- class pytest_routes.validation.response.StatusCodeValidator[source]¶
Bases:
objectValidate response status codes.
Checks that the response status code is within the allowed set. This is the most basic form of response validation.
Example
>>> validator = StatusCodeValidator(allowed_codes=[200, 201, 204]) >>> result = validator.validate(response, route) >>> assert result.valid
Validates that response status codes are within an allowed set.
Example
from pytest_routes import StatusCodeValidator # Allow success and client error codes validator = StatusCodeValidator( allowed_codes=[200, 201, 204, 400, 401, 403, 404, 422] ) # Default: all 2xx-4xx codes (200-499) default_validator = StatusCodeValidator()
ContentTypeValidator¶
- class pytest_routes.validation.response.ContentTypeValidator[source]¶
Bases:
objectValidate response content type.
Checks that the response Content-Type header matches expected types. Useful for ensuring APIs return the correct media type.
Example
>>> validator = ContentTypeValidator(expected_types=["application/json"]) >>> result = validator.validate(response, route) >>> assert result.valid
Validates the Content-Type header of responses.
Example
from pytest_routes import ContentTypeValidator # JSON APIs json_validator = ContentTypeValidator( expected_types=["application/json"] ) # Multiple content types multi_validator = ContentTypeValidator( expected_types=[ "application/json", "application/xml", "text/html", ] )
JsonSchemaValidator¶
- class pytest_routes.validation.response.JsonSchemaValidator[source]¶
Bases:
objectValidate response body against JSON schema.
Uses jsonschema library (if available) to validate response bodies against a provided JSON Schema. Falls back to basic JSON validation if jsonschema is not installed.
Example
>>> schema = {"type": "object", "properties": {"id": {"type": "integer"}}} >>> validator = JsonSchemaValidator(schema=schema) >>> result = validator.validate(response, route) >>> assert result.valid
Validates response bodies against a JSON Schema.
Note
Requires the
jsonschemapackage for full schema validation. Install with:pip install jsonschemaExample
from pytest_routes import JsonSchemaValidator schema = { "type": "object", "required": ["id", "name"], "properties": { "id": {"type": "integer"}, "name": {"type": "string", "minLength": 1}, "email": {"type": "string", "format": "email"}, }, } validator = JsonSchemaValidator(schema=schema, strict=True) result = validator.validate(response, route) if not result.valid: print(f"Schema errors: {result.errors}")
OpenAPIResponseValidator¶
- class pytest_routes.validation.response.OpenAPIResponseValidator[source]¶
Bases:
objectValidate response against OpenAPI schema.
Extracts expected response schemas from an OpenAPI specification and validates responses against them. This is the most comprehensive form of validation for OpenAPI-based APIs.
Example
>>> validator = OpenAPIResponseValidator(openapi_schema=openapi_spec) >>> result = validator.validate(response, route) >>> assert result.valid
Validates responses against an OpenAPI specification.
This validator automatically:
Finds the matching path in the OpenAPI spec
Looks up the expected response schema for the status code
Validates the response body against that schema
Example
from pytest_routes import OpenAPIResponseValidator openapi_spec = { "openapi": "3.0.0", "paths": { "/users/{user_id}": { "get": { "responses": { "200": { "content": { "application/json": { "schema": { "type": "object", "properties": { "id": {"type": "integer"}, "name": {"type": "string"}, }, } } } } } } } } } validator = OpenAPIResponseValidator(openapi_schema=openapi_spec) result = validator.validate(response, route)
CompositeValidator¶
- class pytest_routes.validation.response.CompositeValidator[source]¶
Bases:
objectRun multiple validators in sequence.
Combines multiple validators into a single validator that runs all of them and aggregates their results. Useful for applying multiple validation rules to a single response.
Example
>>> validators = [ ... StatusCodeValidator([200, 201]), ... ContentTypeValidator(["application/json"]), ... JsonSchemaValidator(schema=my_schema), ... ] >>> composite = CompositeValidator(validators) >>> result = composite.validate(response, route) >>> assert result.valid
- Parameters:
validators (
list[ResponseValidator])
Combines multiple validators into one.
All validators are run in sequence, and their results are aggregated. The composite is valid only if all child validators pass.
Example
from pytest_routes import ( CompositeValidator, StatusCodeValidator, ContentTypeValidator, JsonSchemaValidator, ) # Build a comprehensive validator validator = CompositeValidator([ StatusCodeValidator([200, 201]), ContentTypeValidator(["application/json"]), JsonSchemaValidator(schema={ "type": "object", "required": ["data"], }), ]) result = validator.validate(response, route) # Result contains all errors from all validators if not result.valid: for error in result.errors: print(f"Validation error: {error}") # Warnings are also aggregated for warning in result.warnings: print(f"Warning: {warning}")
- __init__(validators)[source]¶
Initialize composite validator.
- Parameters:
validators (
list[ResponseValidator]) – List of validators to run.
Enabling Validation¶
Enable response validation in your configuration:
from pytest_routes import RouteTestConfig
config = RouteTestConfig(
validate_responses=True,
response_validators=["status_code", "content_type"],
fail_on_validation_error=True,
)
Available validator names:
"status_code"-StatusCodeValidator"content_type"-ContentTypeValidator
Custom Validators¶
Create custom validators by implementing the ResponseValidator protocol:
from typing import Any
from pytest_routes import ValidationResult
from pytest_routes.discovery.base import RouteInfo
class ResponseTimeValidator:
"""Validate that responses are fast enough."""
def __init__(self, max_seconds: float = 1.0):
self.max_seconds = max_seconds
def validate(self, response: Any, route: RouteInfo) -> ValidationResult:
# Access response time if available
elapsed = getattr(response, "elapsed", None)
if elapsed is None:
return ValidationResult(
valid=True,
warnings=["Response time not available"]
)
if elapsed.total_seconds() > self.max_seconds:
return ValidationResult(
valid=False,
errors=[
f"Response took {elapsed.total_seconds():.2f}s, "
f"max allowed is {self.max_seconds}s"
]
)
return ValidationResult(valid=True)
class DeprecationHeaderValidator:
"""Check for deprecation warnings in headers."""
def validate(self, response: Any, route: RouteInfo) -> ValidationResult:
warnings = []
if "Deprecation" in response.headers:
warnings.append(
f"Route {route.path} is deprecated: "
f"{response.headers['Deprecation']}"
)
if "Sunset" in response.headers:
warnings.append(
f"Route {route.path} will be removed: "
f"{response.headers['Sunset']}"
)
return ValidationResult(valid=True, warnings=warnings)
Use custom validators with CompositeValidator:
from pytest_routes import CompositeValidator, StatusCodeValidator
validator = CompositeValidator([
StatusCodeValidator([200, 201]),
ResponseTimeValidator(max_seconds=2.0),
DeprecationHeaderValidator(),
])
See Also¶
Configuration - Configuration options for validation
Test Execution - How validation fits into test execution
API Reference - Complete API overview