Chapter 25: Testing
Chapter 25: Testing
Last Updated: 2026-04
25.2 The Infrastructure Test Suite
All infrastructure tests use pytest with the asyncio and httpx plugins. The test suite requires:
pytest
pytest-asyncio
httpx
psycopg2-binary
redis
requests
Python path for the test suite: /opt/anaconda3/bin/python
Test markers
| Marker | Meaning | When to run |
|---|---|---|
@pytest.mark.smoke |
Fast, basic health checks | Every upgrade, every CI run |
@pytest.mark.integration |
Full workflow tests, slower | Pre-release, after major changes |
@pytest.mark.slow |
Long-running tests | Periodic, not on every commit |
Configure markers in pytest.ini:
[pytest]
markers =
smoke: fast health checks
integration: full integration tests
slow: long-running tests
asyncio_mode = auto
25.3 Running Tests
All commands run from ITI/infrastructure/n8n-dify/tests/.
Run all smoke tests
python -m pytest -m smoke -v
Run smoke + integration tests
python -m pytest -m "smoke or integration" -v
Run the full test suite
python -m pytest -v
Run a specific test file
python -m pytest test_docker_health.py -v
Run a specific test
python -m pytest test_n8n_webhooks.py::test_career_coach_webhook -v
25.4 Test Files Reference
| File | Tests | Markers |
|---|---|---|
test_docker_health.py |
All 9 containers healthy; n8n and Dify endpoints respond | smoke |
test_n8n_webhooks.py |
All product webhook endpoints return 200 with expected fields | smoke |
test_n8n_workflows.py |
Full workflow execution with real payloads | integration |
test_postgres_pgvector.py |
DB connectivity; pgvector extension; embedding operations | integration |
test_dify_retrieval.py |
Dify KB retrieval returns relevant results | integration |
25.5 Writing New Tests
Test structure
# test_n8n_webhooks.py
import pytest
import requests
N8N_BASE_URL = "http://localhost:5678"
@pytest.fixture
def n8n_base_url():
return N8N_BASE_URL
@pytest.mark.smoke
def test_n8n_health(n8n_base_url):
"""n8n health endpoint returns OK."""
response = requests.get(f"{n8n_base_url}/healthz", timeout=10)
assert response.status_code == 200
assert response.json().get("status") == "ok"
@pytest.mark.smoke
def test_career_coach_webhook(n8n_base_url):
"""Career coach webhook returns a valid response."""
response = requests.post(
f"{n8n_base_url}/webhook/iti-career-coach-session",
json={"user_message": "I'm a software engineer looking to move into product."},
timeout=60,
)
assert response.status_code == 200
data = response.json()
assert "content" in data
assert len(data["content"]) > 0
Adding a test for a new product webhook
When a new product is added:
- Add a smoke test to
test_n8n_webhooks.py:
@pytest.mark.smoke
def test_new_product_webhook(n8n_base_url):
response = requests.post(
f"{n8n_base_url}/webhook/iti-new-product-action",
json={"test": True, "user_message": "Test message"},
timeout=30,
)
assert response.status_code == 200
assert "content" in response.json()
- Add an integration test to
test_n8n_workflows.pywith a realistic payload. - Update
AI_AGENT_WORKFLOWSlist in the test fixtures.
25.6 Testing the Workflow Adapter Fallback
A critical behavior to verify: when n8n is down, products must continue functioning via the Claude fallback.
# 1. Stop n8n
docker compose stop iti-n8n
# 2. Run the product's integration test
# The test should pass, with source: "claude_fallback" in the response
# 3. Restart n8n
docker compose start iti-n8n
# 4. Verify n8n is healthy
curl -s http://localhost:5678/healthz
25.7 WordPress Plugin Testing
WordPress plugins are tested in a local WordPress installation. See ITI/operations/documentation/WORDPRESS-PLUGIN-TESTING-ENVIRONMENT-SETUP.md for the full setup procedure.
Testing approach:
- Manual testing — install the plugin on local WordPress, test all user-facing features.
- WP-CLI testing — automate plugin activation, setting configuration, and verifying AJAX responses.
- PHPUnit (for larger plugins) — unit test individual class methods, especially database and sanitization functions.
25.8 Swift App Testing
Swift apps use Xcode’s built-in XCTest framework.
import XCTest
@testable import ExpatAdvisor
class ClaudeServiceTests: XCTestCase {
func testCompleteReturnsNonEmptyResponse() async throws {
let response = try await ClaudeService.shared.complete(
system: "You are a helpful assistant.",
user: "Say hello."
)
XCTAssertFalse(response.content.isEmpty)
}
}
Run tests from Xcode: Product > Test (⌘U).
25.9 Testing with Antigravity
Antigravity is the test/debug lane in ITI’s three-tool workflow (Cursor for development, Claude Code for context management, Antigravity for test/debug). It is an agent-first AI IDE powered by Gemini 3 Pro / 3.1 Pro.
Capabilities
- Autonomous test dispatch — configure test agents via
AGENTS.mdat project root; Antigravity dispatches them against the codebase. - Parallel multi-agent debugging — multiple agents investigate failures concurrently, performing root-cause analysis across diffs.
- Browser sub-agent QA — visual regression testing via browser sub-agents with screenshot capture and recording.
Workspace configuration
| Path | Purpose |
|---|---|
AGENTS.md (project root) |
Test agent instructions and dispatch config |
.agents/ |
Antigravity workspace rules, skills, and workflows (committed) |
.antigravity/ |
Session artifacts — logs, screenshots, recordings (gitignored) |
Related skills
| Skill | Purpose |
|---|---|
antigravity-testing |
Autonomous test agent dispatch, artifact review, AGENTS.md config |
antigravity-debugging |
Multi-agent parallel debugging, root cause analysis, diff review |
antigravity-browser-qa |
Browser sub-agent visual regression, screenshot/recording, CI integration |
See ITI/operations/documentation/antigravity-runbook.md for the full operational runbook.
Previous: Chapter 24 — Required Product Artifacts | Next: Chapter 26 — Security Standards
