Back to API Governance Framework
API Testing Strategy & Performance Governance
This document extends the API governance framework to include comprehensive testing capabilities. Testing is not separate from governance—it’s how we verify that governance actually works. The platform’s existing components (Registry, Gateway, Auditor) provide natural integration points for automated testing throughout the API lifecycle.
Table of Contents
- Testing Philosophy
- Testing in the API Lifecycle
- Core Testing Capabilities
- Automated Governance & Quality Gates
- CI/CD Integration
- Testing Infrastructure
Testing Philosophy
Testing as Governance
Traditional API testing happens in isolation—teams run tests in their own environments, results live in CI logs nobody reads, and production issues still surprise everyone. Testing integrated with governance changes this.
When testing data flows through the same platform that manages API lifecycle:
- Test results block publication — APIs cannot reach “Published” state without passing quality gates
- Performance baselines are enforced — New versions must meet or exceed previous version’s latency
- Consumer impact is visible — Before deploying, see how changes affect actual consumers
- Historical trends inform decisions — Auditor tracks performance over time
Shift Left, But Also Shift Right
Shift Left: Catch problems early through contract testing, schema validation, and mock-based integration tests in development.
Shift Right: Production is the ultimate test environment. The Auditor provides continuous performance monitoring that validates what synthetic tests can only estimate.
The platform supports both: rigorous pre-production gates and continuous production validation.
Testing in the API Lifecycle
Testing integrates at every lifecycle stage:
| Stage | Testing Activity | Platform Integration |
|---|---|---|
| Design | Schema validation, mock generation | Registry validates specs (OpenAPI, GraphQL SDL, AsyncAPI); generates mocks automatically |
| Review | Contract compatibility check | Automated breaking change detection before approval |
| Build | Unit tests, contract tests | CI/CD integration via Registry webhooks |
| Pre-Production | Performance baseline, load testing | Gateway routes to test environments; Auditor captures baselines |
| Publication | Quality gate validation | Registry blocks publication if tests fail |
| Production | Continuous performance monitoring | Auditor tracks SLO compliance in real-time |
| Deprecation | Consumer migration verification | Auditor confirms consumers moved to new version |
%%{init: {'theme':'base', 'themeVariables': { 'primaryColor':'#e8f4f8','primaryTextColor':'#000','primaryBorderColor':'#000','lineColor':'#333'}}}%%
flowchart LR
subgraph Design
D1[Schema Validation]
D2[Mock Gen]
end
subgraph Review
R1[Breaking Change Detection]
end
subgraph Build
B1[Contract Tests]
B2[Unit Tests]
end
subgraph Staging
S1[Performance Baseline]
S2[Load Tests]
end
subgraph Prod
P1[Continuous Monitoring]
P2[SLO Tracking]
end
Design --> Review --> Build --> Staging --> Prod
Core Testing Capabilities
This section covers the fundamental testing approaches that validate API behavior, performance, and resilience. These capabilities work together to ensure APIs meet their contracts under normal and adverse conditions.
Contract Testing
The Problem with Integration Testing
Traditional integration tests are:
- Slow — Require all services running together
- Flaky — Fail due to environment issues, not code problems
- Incomplete — Can’t cover all consumer scenarios
- Late — Run after code is written, when changes are expensive
Consumer-Driven Contract Testing
Contract testing inverts the model: consumers define their expectations, producers verify they meet them.
How It Works with the Platform
- Consumers publish contracts to Registry
{ "consumer": "checkout-service", "provider": "inventory-api", "interactions": [ { "description": "get item stock level", "request": { "method": "GET", "path": "/items/12345/stock" }, "response": { "status": 200, "body": { "item_id": "12345", "quantity": 42, "warehouse": "string" } } } ] } - Registry stores contracts alongside subscriptions
- Each subscription can have associated contract expectations
- Contracts versioned with API versions
- Breaking contract = breaking consumer
- Producer CI verifies contracts
- On every build, producer fetches all consumer contracts from Registry
- Tests run against actual implementation
- Failures block deployment
- Registry tracks contract coverage
- Which consumers have contracts?
- Which API endpoints are covered?
- Which interactions are untested?
Contract Testing Workflow
%%{init: {'theme':'base', 'themeVariables': { 'primaryColor':'#e8f4f8','primaryTextColor':'#000','primaryBorderColor':'#000','lineColor':'#333'}}}%%
sequenceDiagram
participant Consumer as Consumer Team
participant Registry as Registry
participant Producer as Producer Team
Consumer->>Registry: 1. Define contract
Registry->>Producer: 2. Notify producer
Producer->>Registry: 3. Fetch contracts
Note over Producer: 4. Run contract tests
Producer->>Registry: 5. Report results
Registry->>Consumer: 5. Contract verified
Breaking Change Detection
The Registry automatically detects breaking changes by comparing new API versions against existing contracts:
Breaking Changes Detected:
- Required field removed from response
- Field type changed (string → integer)
- Endpoint path changed
- Required request parameter added
- Response status code changed for same scenario
Non-Breaking Changes (Safe):
- New optional field in response
- New optional endpoint added
- New optional request parameter
- Expanded enum values (additive)
Registry Analysis on PR:
⚠️ Breaking Changes Detected
Affected Consumers: 3
| Change: Field 'customer_name' removed from GET /orders/{id} | |
|---|---|
| Consumers expecting this field: | |
| checkout-service | 12,000 calls/day |
| reporting-dashboard | 500 calls/day |
| mobile-app-backend | 8,000 calls/day |
| Action Required: Bump to major version (v2 → v3) | |
Protocol-Specific Contract Testing
Contract testing varies by API protocol. The platform supports all three first-class protocols with tailored approaches.
REST (OpenAPI) Contracts
The example above shows REST contract testing. Additional considerations:
- HTTP semantics matter — Status codes, headers, and content types are part of the contract
- Path parameters — Contracts specify expected path patterns and parameter types
- Pagination contracts — Consumers can specify expected pagination behavior
GraphQL Contracts
GraphQL contracts focus on operations and fragments, not endpoints:
{
"consumer": "mobile-app",
"provider": "orders-graphql-api",
"protocol": "graphql",
"interactions": [
{
"description": "fetch order with line items",
"operation": "query",
"query": "query GetOrder($id: ID!) { order(id: $id) { id status lineItems { sku quantity } } }",
"variables": { "id": "order-123" },
"expectedResponse": {
"data": {
"order": {
"id": "order-123",
"status": "string",
"lineItems": [{ "sku": "string", "quantity": "number" }]
}
}
}
}
]
}
GraphQL-Specific Breaking Changes:
| Change | Breaking? | Notes |
|---|---|---|
| Remove field from type | ✅ Yes | Consumers may query this field |
| Change field type | ✅ Yes | Response shape changes |
| Make nullable field non-nullable | ✅ Yes | Consumers may not handle null |
| Add required argument | ✅ Yes | Existing queries will fail |
| Remove type from union | ✅ Yes | Consumers may expect this type |
| Deprecate field | ❌ No | Field still works, just warned |
| Add optional field | ❌ No | Consumers ignore unknown fields |
| Add optional argument | ❌ No | Existing queries still work |
GraphQL Contract Testing Tools:
- Apollo Studio — Schema change detection and field usage tracking
- GraphQL Inspector — CLI for schema diffing and breaking change detection
- Stellate — Schema registry with compatibility checking
AsyncAPI (Event-Driven) Contracts
Event-driven contracts define message schemas and channel bindings:
{
"consumer": "notification-service",
"provider": "orders-events",
"protocol": "asyncapi",
"interactions": [
{
"description": "order created event",
"channel": "orders.created",
"operation": "subscribe",
"message": {
"headers": {
"correlationId": "string",
"timestamp": "string"
},
"payload": {
"orderId": "string",
"customerId": "string",
"totalAmount": "number",
"currency": "string"
}
}
},
{
"description": "order status changed event",
"channel": "orders.status.changed",
"operation": "subscribe",
"message": {
"payload": {
"orderId": "string",
"previousStatus": "string",
"newStatus": "string",
"changedAt": "string"
}
}
}
]
}
AsyncAPI-Specific Breaking Changes:
| Change | Breaking? | Notes |
|---|---|---|
| Remove field from payload | ✅ Yes | Consumers may depend on field |
| Change field type | ✅ Yes | Deserialization will fail |
| Rename channel | ✅ Yes | Consumers subscribed to old name |
| Change message format (JSON→Avro) | ✅ Yes | Consumers can’t deserialize |
| Add required field without default | ✅ Yes | Old messages won’t validate |
| Add optional field | ❌ No | Consumers ignore unknown fields |
| Add new channel | ❌ No | Consumers don’t auto-subscribe |
AsyncAPI Contract Testing Tools:
- AsyncAPI Diff — Schema comparison and breaking change detection
- Specmatic — Contract testing for async APIs
- Schema Registry (Confluent/Apicurio) — Compatibility checking for Avro/JSON Schema
Multi-Protocol Contract Verification
When an API exposes multiple protocols, contracts must be verified across all:
| Orders API Contract Status | ||
|---|---|---|
| REST (OpenAPI) | checkout-service | ✅ 12 interactions verified |
| admin-dashboard | ✅ 8 interactions verified | |
| mobile-app | ✅ 15 interactions verified | |
| GraphQL | mobile-app | ✅ 6 operations verified |
| analytics-service | ⚠️ 2/4 operations verified (2 deprecated) | |
| AsyncAPI (Events) | notification-service | ✅ 3 channels verified |
| audit-logger | ✅ 5 channels verified | |
| inventory-sync | ❌ 1 channel FAILED └─ orders.created: Missing 'warehouseId' field |
|
|
Overall Status: ❌ BLOCKED Fix required before publication |
||
Performance & Load Testing
Why Performance Testing Belongs in Governance
Performance is a feature. An API that returns correct data in 5 seconds isn’t meeting its contract if consumers expect 200ms. The governance platform makes performance:
- Visible — Every API has documented latency expectations
- Measured — Auditor tracks actual performance continuously
- Enforced — Quality gates prevent slow APIs from reaching production
- Comparable — New versions benchmarked against previous versions
Performance Dimensions
| Dimension | Definition | Measurement |
|---|---|---|
| Latency | Time from request to response | p50, p90, p95, p99 percentiles |
| Throughput | Requests handled per second | RPS at various concurrency levels |
| Error Rate | Percentage of failed requests | 4xx, 5xx rates under load |
| Saturation | Resource utilization | CPU, memory, connection pool usage |
| Scalability | Performance change with load | Latency curve as RPS increases |
Performance SLOs in API Specifications
API specifications include performance expectations:
openapi: 3.0.0
info:
title: Order API
version: 2.1.0
x-performance-slo:
latency:
p50: 50ms
p95: 150ms
p99: 300ms
throughput:
minimum_rps: 1000
target_rps: 5000
availability: 99.9%
error_budget:
monthly_downtime: 43m
error_rate: 0.1%
These SLOs are:
- Stored in Registry alongside API metadata
- Displayed in Developer Portal so consumers know what to expect
- Validated by Auditor against actual production metrics
- Enforced by Quality Gates during publication
Platform-Native Load Testing
The Gateway and Auditor provide natural infrastructure for load testing:
%%{init: {'theme':'base', 'themeVariables': { 'primaryColor':'#e8f4f8','primaryTextColor':'#000','primaryBorderColor':'#000','lineColor':'#333'}}}%%
flowchart TB
subgraph Orchestration
Scheduler[Test Scheduler
Registry]
end
subgraph Workers
W1[Worker Node 1]
W2[Worker Node 2]
W3[Worker Node 3]
end
subgraph Gateway Layer
GW[Gateway - Staging
Test traffic tagged with test_run_id]
end
subgraph APIs
A[API A]
B[API B]
C[API C]
end
subgraph Metrics
Auditor[Auditor
Aggregates metrics by test_run_id]
end
Scheduler --> W1
Scheduler --> W2
Scheduler --> W3
W1 --> GW
W2 --> GW
W3 --> GW
GW --> A
GW --> B
GW --> C
A --> Auditor
B --> Auditor
C --> Auditor
Load Test Specification
Load tests are defined declaratively and stored in Registry:
load_test:
name: orders-api-load-test
api: orders-api
version: "2.1"
environment: staging
scenarios:
- name: baseline
description: Normal production-like load
duration: 10m
ramp_up: 2m
virtual_users: 100
requests_per_second: 500
- name: peak
description: 2x expected peak load
duration: 10m
ramp_up: 3m
virtual_users: 200
requests_per_second: 1000
- name: stress
description: Find breaking point
duration: 15m
ramp_up: 5m
virtual_users: 500
requests_per_second: 2500
- name: soak
description: Extended duration stability
duration: 2h
ramp_up: 5m
virtual_users: 100
requests_per_second: 500
workload:
# Weighted distribution of API calls
- endpoint: GET /orders/{id}
weight: 50
parameters:
id: ${random_order_id}
- endpoint: GET /orders?customer_id={id}
weight: 30
parameters:
id: ${random_customer_id}
- endpoint: POST /orders
weight: 15
body: ${order_template}
- endpoint: DELETE /orders/{id}
weight: 5
parameters:
id: ${deletable_order_id}
data_sources:
random_order_id:
type: csv
file: test-data/order-ids.csv
random_customer_id:
type: range
min: 1000
max: 99999
order_template:
type: json_template
file: test-data/order-template.json
deletable_order_id:
type: api
endpoint: POST /test/orders # Creates test order
extract: $.order_id
assertions:
- metric: latency_p95
condition: "<"
threshold: 150ms
- metric: latency_p99
condition: "<"
threshold: 300ms
- metric: error_rate
condition: "<"
threshold: 0.1%
- metric: throughput
condition: ">="
threshold: 500rps
notifications:
on_start:
- slack: #api-platform
on_complete:
- slack: #api-platform
- email: api-owners@company.com
on_failure:
- pagerduty: api-platform-oncall
Real Traffic Replay
The Auditor captures production traffic patterns that can be replayed for realistic load testing:
%%{init: {'theme':'base', 'themeVariables': { 'primaryColor':'#e8f4f8','primaryTextColor':'#000','primaryBorderColor':'#000','lineColor':'#333'}}}%%
flowchart LR
subgraph Production
Logs[Auditor Logs]
end
subgraph Sanitization
Redactor[Redactor]
Redacts[Redacts:
PII, Tokens, Keys]
end
subgraph Staging
Replay[Replay Engine]
end
Logs -->|Raw traffic| Redactor
Redactor -->|Sanitized| Replay
Redactor --> Redacts
Benefits of Traffic Replay:
- Realistic workload distribution — Actual endpoint usage patterns, not guesses
- Edge cases included — Real requests include unusual parameters synthetic tests miss
- Seasonal patterns — Replay Monday morning traffic, month-end spikes, etc.
- Consumer behavior — See how actual consumers call the API
Shadow Traffic Testing
For high-confidence pre-production validation, mirror production traffic to the new version:
%%{init: {'theme':'base', 'themeVariables': { 'primaryColor':'#e8f4f8','primaryTextColor':'#000','primaryBorderColor':'#000','lineColor':'#333'}}}%%
flowchart TB
Request[Production Request]
Gateway[Gateway - Production]
V21[API v2.1 - Current]
V22[API v2.2 - Shadow]
Response[Response returned to client]
Compare[Response compared but discarded]
Comparator[Comparator:
Latency Δ, Response Δ, Error Δ]
Request --> Gateway
Gateway --> V21
Gateway -->|async copy| V22
V21 --> Response
V22 --> Compare
Compare --> Comparator
Shadow Traffic Comparison Report:
| Shadow Traffic Comparison: v2.1 vs v2.2 | |||
|---|---|---|---|
| Duration: 24 hours | Requests: 1,247,832 | |||
| Latency Comparison | |||
| Percentile | v2.1 (prod) | v2.2 (shadow) | Difference |
| p50 | 43ms | 41ms | -4.6% ✅ |
| p95 | 112ms | 108ms | -3.5% ✅ |
| p99 | 198ms | 187ms | -5.5% ✅ |
| Response Comparison | |||
| Identical responses | 1,245,219 | 99.79% | |
| Expected differences | 2,401 | 0.19% ⚠️ | |
| Unexpected differences | 212 | 0.02% ⚠️ | |
| Unexpected Differences (sample) | |||
GET /orders/98234v2.1: {"status": "pending", "items": [...]}v2.2: {"status": "PENDING", "items": [...]}Issue: Enum case change (pending → PENDING) | |||
GET /orders?customer_id=12345&limit=100v2.1: 100 items returned v2.2: 50 items returned Issue: Default limit changed from 100 to 50 | |||
| ⚠️ VERDICT: REVIEW REQUIRED | |||
| 2 potential breaking changes detected in shadow comparison | |||
Chaos Engineering
Why Chaos Engineering?
Load tests verify performance under expected conditions. Chaos engineering verifies resilience under failure conditions:
- What happens when a downstream dependency is slow?
- How does the API behave when the database connection pool is exhausted?
- Do circuit breakers actually trip?
- Is graceful degradation working?
Gateway-Injected Faults
The Gateway can inject faults without modifying backend services:
chaos_experiment:
name: downstream-latency-injection
api: orders-api
environment: staging
# Target specific traffic
traffic_selector:
percentage: 10% # Only affect 10% of requests
# OR target specific consumers
subscription_ids:
- "test-consumer-123"
faults:
- type: latency
delay: 500ms
probability: 0.3 # 30% of selected traffic
- type: error
status_code: 503
probability: 0.1 # 10% of selected traffic
body: '{"error": "service_unavailable"}'
- type: timeout
duration: 30s
probability: 0.05 # 5% of selected traffic
duration: 15m
abort_conditions:
- metric: error_rate
threshold: "> 5%"
action: abort_and_rollback
success_criteria:
- description: "Circuit breaker trips within 30s"
metric: circuit_breaker_open
condition: "== true"
within: 30s
- description: "Error rate stabilizes after circuit opens"
metric: error_rate
condition: "< 1%"
after: circuit_breaker_open
Chaos Experiment Types
| Experiment | Fault Injected | Validates |
|---|---|---|
| Latency injection | Add 100-5000ms delay | Timeout handling, async patterns |
| Error injection | Return 500/503 errors | Retry logic, circuit breakers |
| Partial failure | Fail specific endpoints | Graceful degradation |
| Resource exhaustion | Limit connections | Connection pool sizing |
| Data corruption | Malformed responses | Input validation on consumers |
| Clock skew | Offset timestamps | Token validation, caching |
| Network partition | Block specific routes | Failover, redundancy |
Automated Resilience Scoring
The Auditor calculates a resilience score based on chaos experiment results:
| Resilience Score: orders-api v2.1 | ||
|---|---|---|
| Overall Score: 78/100 ⚠️ | ||
| Category | Score | Status |
| Timeout Handling | 92/100 | ✅ Excellent |
| Circuit Breaker | 85/100 | ✅ Good |
| Retry Logic | 80/100 | ✅ Good |
| Graceful Degradation | 65/100 | ⚠️ Needs Work |
| Error Response Quality | 70/100 | ⚠️ Needs Work |
| Failover Speed | 68/100 | ⚠️ Needs Work |
| Recommendations | ||
| • Graceful degradation: Return cached data when inventory-api is unavailable instead of 503 | ||
| • Error responses: Include retry-after header on 503s | ||
| • Failover: Reduce circuit breaker threshold from 10 to 5 consecutive failures | ||
Automated Governance & Quality Gates
This section centralizes all concepts related to enforcing quality rules through automated governance. It combines performance baselines, regression detection, quality gate configuration, and metrics dashboards to create a cohesive system for maintaining API quality standards.
Performance Baselines
Every API version has a performance baseline established during pre-production testing:
| Performance Baseline: orders-api v2.1 | ||
|---|---|---|
| Endpoint: GET /orders/{id} | ||
| Percentile | Latency | Status |
| p50 | 42ms | |
| p90 | 89ms | |
| p95 | 112ms | SLO Target: 150ms ✅ PASS |
| p99 | 198ms | |
| Summary | ||
| Throughput | 3,200 RPS @ 100 concurrent connections | |
| Error Rate | 0.02% under load | |
| Baseline Date | 2025-11-20 | |
| Test Duration | 15 minutes | |
| Test Environment | staging-us-east-1 | |
Regression Detection
When a new version is submitted, automated performance tests compare against the baseline:
| Performance Comparison: v2.1.0 → v2.2.0 | |||
|---|---|---|---|
| GET /orders/{id} | |||
| Percentile | Baseline (v2.1) | New (v2.2) | Change |
| p50 | 42ms | 45ms | +7% ⚠️ |
| p90 | 89ms | 94ms | +6% ⚠️ |
| p95 | 112ms | 156ms | +39% ❌ |
| p99 | 198ms | 312ms | +58% ❌ |
| ❌ REGRESSION DETECTED | |||
| p95 latency exceeds SLO (150ms) and baseline by >20% | |||
| Possible Causes | |||
| • New database query in OrderService.getOrder() | |||
| • N+1 query pattern detected in order line items | |||
| • Missing index on orders.customer_id | |||
| Action: Publication blocked until regression resolved | |||
Quality Gate Configuration
Define organization-wide quality standards:
# Organization-wide quality gate policy
quality_gates:
# Tier 1: Critical APIs (payments, auth, core data)
tier_1:
contract_tests:
required: true
coverage: ">= 90%"
performance:
baseline_required: true
slo_compliance: required
regression_tolerance: 10%
load_test:
required: true
scenarios: [baseline, peak, stress]
min_duration: 15m
chaos:
required: true
experiments: [latency, errors, timeout]
resilience_score: ">= 80"
security:
owasp_scan: required
dependency_scan: required
# Tier 2: Important APIs (internal services)
tier_2:
contract_tests:
required: true
coverage: ">= 70%"
performance:
baseline_required: true
slo_compliance: required
regression_tolerance: 15%
load_test:
required: true
scenarios: [baseline, peak]
min_duration: 10m
chaos:
required: false
recommended: true
# Tier 3: Low-risk APIs (internal tools, non-critical)
tier_3:
contract_tests:
required: true
coverage: ">= 50%"
performance:
baseline_required: recommended
slo_compliance: recommended
load_test:
required: false
recommended: true
Test Metrics Dashboard
The Auditor provides unified visibility into all test results:
| API Testing Dashboard | |||
|---|---|---|---|
| Test Execution Summary (Last 7 Days) | |||
| Total Tests: 1,247 | Pass Rate: 94.2% | ||
| Test Type | Count | Pass Rate | |
| Contract Tests | 847 | 96% | ████████████████░ |
| Performance Tests | 234 | 91% | ██████████████░░░ |
| Load Tests | 98 | 89% | █████████████░░░░ |
| Chaos Tests | 68 | 94% | ███████████████░░ |
| Quality Gate Status | |||
| APIs Ready for Production: 42/47 | |||
| Blocked APIs | |||
| inventory-api v3.2 | Performance regression | ||
| shipping-api v2.0 | Contract test failures | ||
| auth-api v4.1 | Pending load test | ||
| pricing-api v2.3 | Chaos test failures | ||
| notifications-api v1.5 | Missing baseline | ||
| Performance Trends | |||
| p95 Latency (All APIs, 30 days) Trend: Stable (σ = 12ms) | |||
Automated Performance Test Triggers
Performance tests run automatically at key lifecycle points:
| Trigger | Test Type | Duration | Load Level |
|---|---|---|---|
| PR opened | Smoke test | 2 min | 10% baseline |
| PR merged to main | Baseline test | 10 min | 100% baseline |
| Staging deployment | Load test | 15 min | 100%, 200%, 500% |
| Pre-production approval | Soak test | 1 hour | 100% baseline |
| Canary deployment | Shadow traffic | Continuous | Production mirror |
| Weekly scheduled | Regression check | 30 min | Full suite |
CI/CD Integration
The CI/CD integration is a crucial piece of the implementation puzzle, showing how testing and governance integrate seamlessly into development workflows.
CI/CD Pipeline Integration
# .github/workflows/api-quality.yml
name: API Quality Gates
on:
pull_request:
paths:
- 'apis/**'
- 'openapi/**'
jobs:
contract-tests:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Fetch consumer contracts
run: |
curl -H "Authorization: Bearer $" \
"$/apis/$/contracts" \
-o contracts.json
- name: Run contract tests
run: |
npm run test:contracts -- --contracts contracts.json
- name: Upload results to Registry
run: |
curl -X POST \
-H "Authorization: Bearer $" \
-H "Content-Type: application/json" \
-d @test-results.json \
"$/apis/$/test-results"
performance-baseline:
runs-on: ubuntu-latest
needs: contract-tests
steps:
- name: Deploy to ephemeral environment
run: |
kubectl apply -f k8s/ephemeral-env.yaml
- name: Run performance baseline
run: |
k6 run \
--out json=results.json \
--tag testid=$ \
performance/baseline.js
- name: Compare with previous baseline
run: |
curl -X POST \
-H "Authorization: Bearer $" \
-H "Content-Type: application/json" \
-d @results.json \
"$/apis/$/performance/compare"
- name: Check quality gate
run: |
RESULT=$(curl -s "$/apis/$/quality-gate")
if [ "$(echo $RESULT | jq -r '.passed')" != "true" ]; then
echo "Quality gate failed:"
echo $RESULT | jq '.failures'
exit 1
fi
Testing Infrastructure
Test Environment Management
The platform provides isolated test environments that mirror production:
%%{init: {'theme':'base', 'themeVariables': { 'primaryColor':'#e8f4f8','primaryTextColor':'#000','primaryBorderColor':'#000','lineColor':'#333'}}}%%
flowchart TB
subgraph Production
PGW[Gateway - prod]
PRG[Registry - prod]
PAU[Auditor - prod]
PAP[APIs - prod]
end
subgraph Staging
SGW[Gateway - staging]
SRG[Registry - staging]
SAU[Auditor - staging]
SAP[APIs - staging]
SN1[Production config synced daily]
SN2[Synthetic test data]
SN3[Full load testing capability]
end
subgraph Ephemeral["Ephemeral Test Environments"]
PR1[PR #1234
orders-api v2.2-pr1234
TTL: 24h]
PR2[PR #1235
users-api v3.1-pr1235
TTL: 24h]
PR3[PR #1236
orders-api v2.2-pr1236
TTL: 24h]
EN1[Spun up automatically on PR]
EN2[Destroyed after merge/close]
EN3[Contract tests only]
end
Production -->|Config Mirror| Staging
Staging -->|On-Demand Envs| Ephemeral
Test Data Management
test_data_strategy:
production_data:
# Never use real production data
policy: prohibited
synthetic_data:
# Generated to match production patterns
generators:
- type: faker
locale: en_US
seed: 12345 # Reproducible
- type: production_statistics
# Generate data matching production distributions
source: auditor_metrics
anonymized_data:
# Production data with PII removed
pipeline:
- extract: production_snapshot
- transform: anonymize_pii
- transform: scramble_ids
- load: staging_database
schedule: weekly
test_fixtures:
# Known data for deterministic tests
location: test-data/fixtures/
version_controlled: true
Load Generator Infrastructure
Dedicated infrastructure for generating load:
load_generator:
# Kubernetes-based distributed load generation
infrastructure:
type: kubernetes
namespace: load-testing
workers:
image: company/load-generator:latest
replicas:
min: 3
max: 50
auto_scale: true
resources:
cpu: 2
memory: 4Gi
distribution:
# Spread workers across regions for realistic latency
regions:
- us-east-1: 40%
- us-west-2: 30%
- eu-west-1: 30%
tools:
primary: k6 # Modern, scriptable
alternatives:
- locust # Python-based
- gatling # Scala-based
- vegeta # Simple HTTP load
Summary
Testing integrated with API governance transforms quality from an afterthought to a core capability:
| Traditional Testing | Governance-Integrated Testing |
|---|---|
| Tests run in isolation | Tests inform lifecycle decisions |
| Results in CI logs | Results in Auditor dashboards |
| Pass/fail binary | Trend analysis and regression detection |
| Manual performance benchmarks | Automated baseline comparison |
| Load tests on request | Scheduled, triggered, continuous |
| Chaos as special project | Chaos as routine validation |
| Quality gates per team | Organization-wide standards |
The platform’s existing components provide natural integration points:
- Registry stores test specifications, contracts, and quality gate configurations
- Gateway enables fault injection, traffic mirroring, and test traffic routing
- Auditor aggregates results, tracks trends, and enforces quality gates
This approach ensures APIs meet quality standards before they impact consumers—and continues validating them in production.
| Back to Technical Design | Back to Main README |