test-api-x
Async API testing framework with pluggable authentication for Python 3.12+
Requirements
- Python 3.12 or higher
- Poetry 1.5+ (for development)
Installation
pip install test-api-x
Features
- Async HTTP Client: Built on httpx with automatic retries and timeout handling
- Secure Logging: Automatic credential masking with correlation IDs for request tracing
- Fluent Assertions: Chainable assertions for response validation
- Enhanced Response: Rich response objects with JSON path queries and validation
- Pluggable Authentication: Support for Basic Auth and Auth0 with automatic session management
- User Registry: Multi-persona authentication with pool-based organization and environment variable substitution
- Factory Methods: Ergonomic client creation with built-in authentication
- Plugin System: Extensible architecture for custom fixtures and authentication providers
Quick Start
Basic Usage
from test_api_x import Client, assert_that
async with Client(base_url="https://api.example.com") as client:
response = await client.get("/users")
assert_that(response).has_status(200).has_json_path("users")
With Authentication
from test_api_x import Client
# Basic Authentication
async with Client.with_basic_auth(
username="admin",
password="secret123",
base_url="https://api.example.com"
) as client:
response = await client.get("/protected")
assert_that(response).has_status(200)
# Auth0 Authentication
async with Client.with_auth0(
domain="your-tenant.auth0.com",
client_id="your-client-id",
client_secret="your-client-secret",
username="user@example.com",
password="password",
base_url="https://api.example.com"
) as client:
response = await client.get("/protected")
assert_that(response).has_status(200)
With User Registry
from test_api_x import UserRegistry, Client
# Load users from YAML
registry = UserRegistry.from_yaml("users.yaml")
# Get client for specific persona
async with Client.from_registry(
registry=registry,
persona="admin",
base_url="https://api.example.com"
) as client:
response = await client.get("/admin/users")
assert_that(response).has_status(200)
Logging
test-api-x includes secure logging with automatic credential masking to prevent sensitive data leaks.
Basic Usage
from test_api_x import get_logger
logger = get_logger("my_module")
logger.info("Starting test execution")
Automatic Request/Response Logging
The Client automatically logs all HTTP requests and responses with correlation IDs for tracing:
import os
os.environ["TESTAPIX_LOG_LEVEL"] = "DEBUG"
async with Client(base_url="https://api.example.com") as client:
# Automatically logs request/response with correlation ID
response = await client.post("/auth", json={
"username": "admin",
"password": "secret123" # Automatically masked in logs
})
Credential Masking
Sensitive data is automatically detected and masked in:
- HTTP headers (Authorization, X-API-Key, etc.)
- Request/response bodies (password, token, api_key fields)
- URLs (query parameters and basic auth)
Masked data appears as ***REDACTED*** in logs.
Log Levels
Set the log level via environment variable:
export TESTAPIX_LOG_LEVEL=DEBUG # DEBUG, INFO, WARNING, ERROR
User Registry
Manage multiple test users with different personas and authentication methods.
Basic YAML Structure
users:
- user_id: admin_user
persona: admin
auth_method: basic
username: admin
password: admin123
- user_id: auth0_user
persona: standard_user
auth_method: auth0
domain: your-tenant.auth0.com
client_id: your-client-id
client_secret: your-client-secret
username: user@example.com
password: password
Pool-Based Organization
Organize users into pools for different environments:
pools:
dev:
users:
- user_id: dev_admin
persona: admin
auth_method: basic
username: dev_admin
password: dev_pass
staging:
users:
- user_id: staging_admin
persona: admin
auth_method: basic
username: staging_admin
password: staging_pass
Usage:
# Get user from specific pool
async with Client.from_registry(
registry=registry,
persona="admin",
pool="staging",
base_url="https://staging-api.example.com"
) as client:
response = await client.get("/users")
Environment Variable Substitution
Use environment variables for sensitive credentials:
users:
- user_id: admin_user
persona: admin
auth_method: basic
username: ${ADMIN_USERNAME}
password: ${ADMIN_PASSWORD}
The registry automatically substitutes ${VAR_NAME} with environment variable values.
Plugin System
Extend test-api-x with custom fixtures and authentication providers.
Using Plugins
from test_api_x.plugins import PluginManager
# Automatically discover installed plugins
manager = PluginManager()
manager.discover_plugins()
# Use plugin fixtures
helper = manager.get_fixture("example_helper")()
result = helper.greet("World")
Creating Plugins
from test_api_x.plugins import Plugin
class MyPlugin(Plugin):
@property
def name(self) -> str:
return "my_plugin"
def register_fixtures(self) -> dict:
return {"my_helper": self._my_helper_fixture}
def register_auth_providers(self) -> dict:
return {}
def _my_helper_fixture(self):
return MyHelper()
See Plugin Development Guide for details.
Response Assertions
Validate API responses with fluent assertions:
# Status code assertions
assert_that(response).has_status(200)
assert_that(response).has_status_in_range(200, 299)
# JSON assertions
assert_that(response).has_json_matching({"status": "success"})
assert_that(response).has_json_path("data.users[0].id")
# Header assertions
assert_that(response).has_header("Content-Type", "application/json")
# Response time assertions
assert_that(response).responded_within(1000) # milliseconds
Development
Setup
# Clone the repository
git clone https://github.com/yourusername/test-api-x.git
cd test-api-x
# Install dependencies
poetry install
Running Quality Checks
# Run all tests (285 tests, 96.50% coverage)
poetry run pytest
# Run only unit tests (up to 198 tests)
poetry run pytest -m unit
# Run only integration tests (21 tests)
poetry run pytest -m integration
# Run tests with coverage report
poetry run pytest --cov=src/test_api_x --cov-report=html
# Format code
poetry run black src/ tests/
# Lint code
poetry run ruff check src/ tests/
# Type check
poetry run mypy src/
Development Workflow
The project includes a pre-commit hook that automatically runs:
- Black code formatting check
- Ruff linting
- MyPy type checking
All checks must pass before commits are accepted.
Project Status
Phase 3 In Progress - Plugin system implemented
Completed:
- Core HTTP client with retries and timeout handling
- Enhanced response objects with JSON path queries
- Fluent assertion API
- Secure logging with automatic credential masking
- Correlation IDs for request tracing
- Pluggable authentication system (Basic Auth, Auth0)
- Session management with automatic caching
- User registry with multi-persona support
- Pool-based user organization
- Environment variable substitution
- Factory methods for ergonomic client creation
- Plugin system with entry point discovery
- 96.50% test coverage (285 tests: 198 unit, 21 integration)
Coming Soon:
- Official plugins (AWS, Database, Mocking)
- Enhanced retry strategies
- Request/response middleware
- Performance optimizations
License
MIT
Metadata
Release files for test-api-x 0.3.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | |
|---|---|---|---|---|
| test_api_x-0.3.0.tar.gz | 27.0 kB | Without provenance | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| test_api_x-0.3.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 60.2 kB
Release files / test_api_x-0.3.0.tar.gz
| Download URL | test_api_x-0.3.0.tar.gz |
|---|---|
| Size | 27.0 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
a9fa0df1216be8bd99c73f7350a4b79fc62b382173df6d55c3f9580d83e186bf
|
|
BLAKE2b-256 checksum How to use checksums |
afab5d5e542c07f6ad9ccdd541a011cd07b3b31e42d8306d5a987e868518b163
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
poetry/2.1.4 CPython/3.12.8 Darwin/24.6.0
|
Release files / test_api_x-0.3.0-py3-none-any.whl
| Download URL | test_api_x-0.3.0-py3-none-any.whl |
|---|---|
| Size | 33.2 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
ebf9fad904fc76e0d2eae4bcae4b9cfe350fd9920d1bb6ff1b0738cd129ad977
|
|
BLAKE2b-256 checksum How to use checksums |
1c440f005304e04b2c729878adc49c7254c742890d6588919b706e9a627b12f8
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
poetry/2.1.4 CPython/3.12.8 Darwin/24.6.0
|
Security for test-api-x 0.3.0
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.