A set of pytest fixtures to test Flask applications.
—
Pre-configured HTTP Accept header fixtures for testing content negotiation and API responses. Provides standardized header configurations for common MIME types and content negotiation scenarios.
Accept header specifically configured for JSON content type, commonly used for API testing.
@pytest.fixture
def accept_json(request):
"""
Accept header for JSON content type.
Returns:
list: [("Accept", "application/json")]
"""Usage Example:
def test_json_api_endpoint(client, accept_json):
"""Test API endpoint that returns JSON"""
response = client.get('/api/users', headers=accept_json)
assert response.status_code == 200
assert response.content_type == 'application/json'
assert isinstance(response.json, list)
def test_content_negotiation_json(client, accept_json):
"""Test content negotiation preferring JSON"""
response = client.get('/api/data', headers=accept_json)
assert response.status_code == 200
assert 'application/json' in response.content_type
# Verify JSON structure
data = response.json
assert 'items' in data
assert 'total' in dataAccept header configured for JSONP (JSON with Padding) content type, used for cross-domain requests.
@pytest.fixture
def accept_jsonp():
"""
Accept header for JSONP content type.
Returns:
list: [("Accept", "application/json-p")]
"""Usage Example:
def test_jsonp_endpoint(client, accept_jsonp):
"""Test JSONP endpoint for cross-domain requests"""
response = client.get('/api/jsonp-data',
headers=accept_jsonp,
query_string={'callback': 'myCallback'})
assert response.status_code == 200
assert response.content_type == 'application/json-p'
assert response.data.decode().startswith('myCallback(')
def test_jsonp_callback_handling(client, accept_jsonp):
"""Test JSONP callback parameter handling"""
callback_name = 'processData'
response = client.get('/api/stats',
headers=accept_jsonp,
query_string={'callback': callback_name})
assert response.status_code == 200
content = response.data.decode()
assert content.startswith(f'{callback_name}(')
assert content.endswith(');')Parametrized fixture that tests multiple common MIME types, useful for testing content negotiation across different formats.
@pytest.fixture(params=["application/json", "text/html"])
def accept_mimetype(request):
"""
Parametrized fixture for common MIME types.
Parameters:
request.param: One of "application/json" or "text/html"
Returns:
list: [("Accept", mimetype)] for each parameter
"""Usage Example:
def test_content_negotiation(client, accept_mimetype):
"""Test endpoint supports multiple content types"""
response = client.get('/api/flexible-endpoint', headers=accept_mimetype)
assert response.status_code == 200
# Check response matches requested content type
if accept_mimetype == [("Accept", "application/json")]:
assert 'application/json' in response.content_type
assert response.json is not None
elif accept_mimetype == [("Accept", "text/html")]:
assert 'text/html' in response.content_type
assert '<html>' in response.data.decode()
def test_api_format_support(client, accept_mimetype):
"""Test API supports both JSON and HTML responses"""
response = client.get('/api/users/123', headers=accept_mimetype)
assert response.status_code == 200
content_type = response.content_type
if 'json' in content_type:
user_data = response.json
assert 'id' in user_data
assert 'name' in user_data
elif 'html' in content_type:
html_content = response.data.decode()
assert 'User Profile' in html_content
assert 'id="user-123"' in html_contentParametrized fixture for wildcard accept headers, testing endpoints that accept any content type.
@pytest.fixture(params=["*", "*/*"])
def accept_any(request):
"""
Accept header for any content type.
Parameters:
request.param: One of "*" or "*/*"
Returns:
list: [("Accept", wildcard_type)] for each parameter
"""Usage Example:
def test_accepts_any_content(client, accept_any):
"""Test endpoint accepts any content type"""
response = client.get('/api/flexible', headers=accept_any)
assert response.status_code == 200
# Endpoint should respond with its default content type
assert response.content_type is not None
def test_default_content_type(client, accept_any):
"""Test default content type when accepting anything"""
response = client.get('/api/data', headers=accept_any)
assert response.status_code == 200
# Should default to JSON for API endpoints
assert 'application/json' in response.content_type
assert response.json is not None
def test_proxy_requests(client, accept_any):
"""Test proxy endpoint that passes through various content types"""
# Test with different upstream content types
response = client.get('/proxy/external-api', headers=accept_any)
assert response.status_code in [200, 304] # Success or not modifiedCombine fixtures for complex content negotiation testing:
def test_multiple_accept_types(client):
"""Test with multiple accept types in priority order"""
headers = [
("Accept", "application/json"),
("Accept", "application/xml"),
("Accept", "text/html")
]
response = client.get('/api/content-negotiation', headers=headers)
assert response.status_code == 200
# Should return highest priority supported type
def test_quality_values(client):
"""Test Accept header with quality values"""
headers = [("Accept", "application/json;q=0.9, text/html;q=0.8")]
response = client.get('/api/data', headers=headers)
assert response.status_code == 200
# Should prefer JSON due to higher quality value
assert 'application/json' in response.content_typeUse accept header fixtures with other pytest-flask fixtures:
@pytest.mark.options(api_version='v2')
def test_versioned_api_json(client, accept_json, config):
"""Test versioned API with JSON response"""
headers = accept_json + [("API-Version", config['API_VERSION'])]
response = client.get('/api/users', headers=headers)
assert response.status_code == 200
assert response.json['version'] == 'v2'
def test_live_server_content_negotiation(live_server, accept_json):
"""Test content negotiation with live server"""
import requests
headers = dict(accept_json)
response = requests.get(
live_server.url('/api/external'),
headers=headers
)
assert response.status_code == 200
assert response.headers['content-type'] == 'application/json'Test how applications handle unsupported content types:
def test_unsupported_content_type(client):
"""Test response to unsupported Accept header"""
headers = [("Accept", "application/xml")]
response = client.get('/api/json-only', headers=headers)
# Should return 406 Not Acceptable or fallback to default
assert response.status_code in [200, 406]
if response.status_code == 406:
assert 'Not Acceptable' in response.data.decode()
else:
# Fallback to default JSON
assert 'application/json' in response.content_typeInstall with Tessl CLI
npx tessl i tessl/pypi-pytest-flask