# 3. Test Renderers - System Design > **Priority**: 🟒 MEDIUM β€” Deterministic layer > **Complexity**: Medium > **Effort Estimate**: 8-12 hours --- ## Overview Test Renderers **deterministically transform** `EvalSpec` JSON into runnable test files. Key insight: - **Claude generates specs** (what to test, inputs, assertions) - **Renderers generate code** (deterministic, templated, no LLM) This makes tests reliable, debuggable, and version-controllable. --- ## Architecture ``` β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ Renderer Pipeline β”‚ β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ β”‚ β”‚ EvalSpec │───▢│ Renderer │───▢│ Test Files β”‚ β”‚ β”‚ β”‚ JSON β”‚ β”‚ (per-lang) β”‚ β”‚ (.py/.ts) β”‚ β”‚ β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ β”‚ β”‚ β”‚ Supported: pytest (Python) | vitest (TS) | jest (TS) β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ ``` --- ## Core Types ```typescript interface RenderOptions { outputDir: string; framework: 'pytest' | 'vitest' | 'jest'; includeFixtures: boolean; generateMocks: boolean; } interface RenderResult { files: GeneratedFile[]; stats: { scenarioCount: number; fileCount: number; assertionCount: number }; } interface GeneratedFile { path: string; content: string; scenarios: string[]; // Which scenario IDs } ``` --- ## Assertion Mapping | EvalSpec Type | Python (pytest) | TypeScript (vitest) | |---------------|-----------------|---------------------| | `equals` | `assert result == expected` | `expect(result).toBe(expected)` | | `contains` | `assert key in result` | `expect(result).toContain(key)` | | `matches` | `assert re.match(pattern, result)` | `expect(result).toMatch(pattern)` | | `throws` | `pytest.raises(ExceptionType)` | `expect(() => fn()).toThrow()` | | `type` | `assert isinstance(result, Type)` | `expect(typeof result).toBe('type')` | --- ## Example Transformation **EvalSpec scenario:** ```json { "id": "auth-login-success", "target": { "module": "src/auth/login.py", "function": "login" }, "input": { "args": { "username": "test", "password": "valid" } }, "assertions": [ { "type": "type", "target": "return", "expected": "dict" }, { "type": "contains", "target": "return", "expected": "token" } ] } ``` **Generated pytest:** ```python def test_auth_login_success(): """Verify login returns JWT on valid credentials""" result = login("test", "valid") assert isinstance(result, dict) assert "token" in result ``` --- ## File Structure ``` src/renderers/ β”œβ”€β”€ index.ts # Registry + main export β”œβ”€β”€ types.ts # Interfaces β”œβ”€β”€ base.ts # Abstract base renderer β”œβ”€β”€ python/ β”‚ β”œβ”€β”€ pytest-renderer.ts β”‚ β”œβ”€β”€ assertions.ts β”‚ └── templates/ β”‚ └── test-file.py.hbs β”œβ”€β”€ typescript/ β”‚ β”œβ”€β”€ vitest-renderer.ts β”‚ β”œβ”€β”€ jest-renderer.ts β”‚ └── assertions.ts └── utils/ └── template-engine.ts ``` --- ## Incremental Rendering ```typescript async function renderIncremental( spec: EvalSpec, options: RenderOptions, changedFiles: string[] ): Promise { const filteredSpec = { ...spec, scenarios: spec.scenarios.filter(s => changedFiles.some(f => s.target.module.includes(f)) ), }; return renderSpec(filteredSpec, options); } ``` --- ## Dependencies ```json { "handlebars": "^4.7.8" } ``` --- ## Success Criteria - [ ] Pytest renderer generates valid Python test files - [ ] Vitest renderer generates valid TypeScript test files - [ ] Generated tests pass linting - [ ] All assertion types are supported - [ ] Mocks and fixtures correctly generated - [ ] Incremental rendering works