with one click
testing-strategies
// Kailash testing: 3-tier, Tier 2/3 real infra (NO mocking per rules/testing.md), regression, coverage.
// Kailash testing: 3-tier, Tier 2/3 real infra (NO mocking per rules/testing.md), regression, coverage.
[HINT] Download the complete skill directory including SKILL.md and all related files
| name | testing-strategies |
| description | Kailash testing โ 3-tier, Tier 2/3 real infra (NO mocking), regression, coverage. |
3-tier testing strategy for Kailash applications. Tier 2/3 require real infrastructure โ NO mocking (@patch, MagicMock, unittest.mock are BLOCKED) per rules/testing.md.
Use when asking about testing, test strategy, 3-tier testing, unit tests, integration tests, end-to-end tests, testing workflows, testing DataFlow, testing Nexus, real infrastructure, NO mocking, test organization, or testing best practices.
rules/probe-driven-verification.md.| Tier | Scope | Mocking | Speed | Infrastructure |
|---|---|---|---|---|
| 1 - Unit | Functions, classes | Allowed | <1s/test | None |
| 2 - Integration | Workflows, DB, APIs | BLOCKED โ real infra only | 1-10s/test | Real DB, real runtime |
| 3 - E2E | Complete user flows | BLOCKED โ real infra only | 10s+/test | Real HTTP, real everything |
Why: Mocking hides database constraints, API timeouts, race conditions, connection pool exhaustion, schema migration issues, and LLM token limits.
What to use instead: Test databases (Docker containers), test API endpoints, test LLM accounts (with caching), temp directories.
@pytest.fixture
def db():
"""Real database for testing."""
db = DataFlow("postgresql://test:test@localhost:5433/test_db")
db.create_tables()
yield db
db.drop_tables()
@pytest.fixture
def runtime():
return LocalRuntime()
tests/
tier1_unit/ # Mocking allowed
tier2_integration/ # Real infrastructure
tier3_e2e/ # Full system
conftest.py # Shared fixtures
| Component | Tier | Key Point |
|---|---|---|
| Workflows | 2 | Real runtime execution, verify results["node"]["result"] |
| DataFlow | 2 | Real DB, verify with read-back after write |
| Nexus API | 3 | Real HTTP requests to running server |
| Kaizen Agents | 2 | Real LLM calls with response caching |
Regression tests lock in bug fixes. They MUST exercise the actual code path -- call the function, assert the raise or return value. Source-grep tests are BLOCKED as the sole assertion because they pin the implementation, not the contract: when the fix moves to a shared helper (the right refactor), the grep breaks even though the protection is still in place.
# Behavioral (survives refactors)
@pytest.mark.regression
def test_null_byte_rejected():
parsed = urlparse("mysql://user:%00x@h/db")
with pytest.raises(ValueError, match="null byte"):
decode_userinfo_or_raise(parsed)
# Source-grep (BLOCKED as sole assertion)
def test_null_byte_exists_in_source():
assert "\\x00" in open("src/kailash/db/connection.py").read()
See rules/testing.md "MUST: Behavioral Regression Tests Over
Source-Grep" for the full rule and rationale.
Unit and integration tests per primitive cannot observe the handoff between primitives; each primitive's tests construct test fixtures with exactly the fields it needs, and the chain between A โ B fails only when A's real output is missing a field B actually needs. For every pipeline the docs teach (README Quick Start, tutorial, specs/*.md canonical example), add a regression test that executes the docs-exact code against real infrastructure AND asserts a deterministic fingerprint over the output. Flipped fingerprints block release. See skills/16-validation-patterns/SKILL.md ยง "End-to-End Pipeline Regression Above Unit/Integration" for the full pattern + kailash-ml 1.0.0 W33b evidence, and rules/testing.md ยง "End-to-End Pipeline Regression Tests Above Unit + Integration" for the MUST clause.
Tests that exercise optional extras (e.g., [hpo], [redis], [vault])
MUST guard against the dependency being absent. Use pytest.importorskip
at module or class scope so the test is skipped (not failed) in CI
environments that don't install the extra.
# At module level โ skips entire file if optuna is missing
optuna = pytest.importorskip("optuna", reason="optuna required for HPO tests")
class TestSuccessiveHalving:
@pytest.mark.asyncio
async def test_pruning(self):
# optuna is guaranteed available here
...
Why: Base CI installs core dependencies only. A test that imports
an optional extra without a skip guard fails every CI matrix entry,
blocking unrelated PRs. pytest.importorskip is the standard
mechanism โ it imports the module if available and calls pytest.skip
if not.
Where to place the guard: Before the first use of the optional module โ typically at module scope (before the test class) or inside a fixture. Placing it inside a test function body is too late if the class-level setup already depends on the import.
@patch/MagicMock/unittest.mockpytest tests/tier1_unit/ # Fast CI
pytest tests/tier2_integration/ # With real infra
pytest tests/tier3_e2e/ # Full system
pytest --cov=app --cov-report=html # Coverage
testing-specialist - Testing strategies and patternstdd-implementer - Test-driven developmentdataflow-specialist - DataFlow testing patterns