Generator Contract Specification¶
Status: Canonical Reference
Scope: All generator files ingenerators/
Last Updated: January 2, 2026 15:35:14
Created: December 12, 2025 15:38:10
This document defines the contract for test case generator files. Generators enable stress testing, edge case discovery, and reproducible test generation.
Table of Contents¶
- File Structure
- generate() Function
- Generator Design Patterns
- Complexity Estimation Generator
- Input Format Specifications
- JUDGE_FUNC Requirement
- Running Generated Tests
- Best Practices
- Quick Reference
File Structure¶
Naming Convention¶
| Component | Format | Example |
|---|---|---|
problem_id | 4-digit zero-padded LeetCode ID | 0001, 0004, 0051 |
slug | snake_case problem name | two_sum, median_of_two_sorted_arrays |
Examples: - generators/0001_two_sum.py - generators/0004_median_of_two_sorted_arrays.py - generators/0051_n_queens.py
Required Elements¶
Every generator file MUST contain:
| Element | Required | Description |
|---|---|---|
generate() function | β | Main entry point for test generation |
| Docstring with constraints | β | LeetCode constraints documentation |
| Edge cases | β | Known edge cases yielded first |
Optional Elements¶
| Element | Optional | Description |
|---|---|---|
generate_for_complexity() | β | For time complexity estimation |
| Helper functions | β | Internal _generate_case() etc. |
| Custom generators | β | generate_all_sizes() etc. |
generate() Function¶
Function Signature¶
def generate(count: int = 10, seed: Optional[int] = None) -> Iterator[str]:
"""
Generate random test case inputs.
Args:
count: Number of test cases to generate
seed: Random seed for reproducibility (optional)
Yields:
str: Test input in the same format as .in files
"""
Contract Rules¶
| Rule | Requirement | Rationale |
|---|---|---|
| Yield format | Must match .in file format | Runner passes to solve() via stdin |
| Reproducibility | Same seed β same output | Enables failure reproduction |
| Edge cases first | Yield known edge cases before random | Catch corner-case bugs early |
| Constraint compliance | Respect LeetCode constraints | Ensure valid test cases |
| JUDGE_FUNC required | Solution must have JUDGE_FUNC | No .out file for generated cases |
π See JUDGE_FUNC Specification for validation details.
Minimal Example¶
# generators/0001_two_sum.py
import json
import random
from typing import Iterator, Optional
def generate(count: int = 10, seed: Optional[int] = None) -> Iterator[str]:
"""Generate test cases for Two Sum."""
if seed is not None:
random.seed(seed)
# Edge cases first (using canonical JSON format)
edge_cases = [
([2, 7, 11, 15], 9), # Classic example
([3, 2, 4], 6), # Answer not first element
([3, 3], 6), # Duplicate values
]
for nums, target in edge_cases:
yield f"{json.dumps(nums, separators=(',', ':'))}\n{target}"
count -= 1
if count <= 0:
return
# Random cases
for _ in range(count):
yield _generate_case()
def _generate_case() -> str:
size = random.randint(2, 5000)
nums = [random.randint(-10**6, 10**6) for _ in range(size)]
i, j = random.sample(range(size), 2)
target = nums[i] + nums[j]
return f"{json.dumps(nums, separators=(',', ':'))}\n{target}"
Generator Design Patterns¶
Standard Template¶
# generators/{problem_id}_{slug}.py
"""
Test Case Generator for Problem {ID} - {Title}
LeetCode Constraints:
- {constraint_1}
- {constraint_2}
- ...
Time Complexity: O(?)
"""
import random
from typing import Iterator, Optional
# ============================================
# Random Test Generation (for functional testing)
# ============================================
def generate(count: int = 10, seed: Optional[int] = None) -> Iterator[str]:
"""
Generate random test case inputs.
Args:
count: Number of test cases to generate
seed: Random seed for reproducibility (optional)
Yields:
str: Test input in the same format as .in files
"""
if seed is not None:
random.seed(seed)
# Edge cases first
edge_cases = [
# Known important test cases
]
for edge in edge_cases:
yield edge
count -= 1
if count <= 0:
return
# Random cases
for _ in range(count):
yield _generate_case()
def _generate_case() -> str:
"""Generate a single random test case."""
# Implementation here
pass
# ============================================
# Complexity Estimation (controlled size)
# ============================================
def generate_for_complexity(n: int) -> str:
"""
Generate test case with specific input size for complexity estimation.
Args:
n: Target input size
Returns:
str: Test input with size approximately n
"""
pass
Edge Case Design¶
Edge cases should cover:
| Category | Examples |
|---|---|
| Boundary values | Min/max constraints, empty inputs |
| Special cases | Single element, all same values |
| Negative cases | Negative numbers, zero |
| Classic examples | LeetCode example inputs |
Example (Median of Two Sorted Arrays):
import json
# Store as data structures, not strings
edge_cases = [
([], [1]), # nums1 is empty
([1], []), # nums2 is empty
([1, 3], [2]), # Classic odd total length
([1, 2], [3, 4]), # Classic even total length
([-5, -3, -1], [2, 4, 6]), # Negative and positive
([1], [1]), # Same single element
]
for nums1, nums2 in edge_cases:
yield f"{json.dumps(nums1, separators=(',', ':'))}\n{json.dumps(nums2, separators=(',', ':'))}"
Guaranteed Valid Input¶
For problems requiring valid solutions exist, ensure generated inputs are solvable:
def _generate_case(size: int) -> str:
"""
Generate a Two Sum case with guaranteed solution.
Strategy:
1. Generate random array
2. Pick two random indices
3. Set target = nums[i] + nums[j]
"""
nums = [random.randint(-10**6, 10**6) for _ in range(size)]
i, j = random.sample(range(size), 2)
target = nums[i] + nums[j] # Guaranteed to have solution
return f"{','.join(map(str, nums))}\n{target}"
Weighted Random Distribution¶
For more thorough testing, weight towards challenging cases:
def generate(count: int = 10, seed: Optional[int] = None) -> Iterator[str]:
# ...
for _ in range(count):
# Weight towards larger n (more thorough testing)
n = random.choices(
population=range(1, 10),
weights=[1, 1, 2, 3, 4, 5, 6, 7, 8], # Higher weight for larger
k=1
)[0]
yield str(n)
Complexity Estimation Generator¶
Function Signature¶
def generate_for_complexity(n: int) -> str:
"""
Generate test case with specific input size for complexity estimation.
Args:
n: Target input size
Returns:
str: Test input with size approximately n
"""
Purpose¶
The --estimate flag uses this function to: 1. Generate test cases of increasing sizes 2. Measure execution time for each size 3. Fit curve to estimate Big-O complexity
π See Test Runner Β§ Complexity Estimation for usage.
Example¶
def generate_for_complexity(n: int) -> str:
"""
Generate test case with specific input size.
For Two Sum:
- n is the length of nums array
- Expected complexity: O(n) with hash map
"""
n = max(2, n) # Ensure minimum valid size
return _generate_case(n)
Size Semantics¶
Define what "n" means for your problem:
| Problem Type | n Meaning |
|---|---|
| Array problems | Array length |
| String problems | String length |
| Two-array problems | Total elements (m + n) |
| Matrix problems | Total cells (rows Γ cols) |
| Graph problems | Number of nodes or edges |
Input Format Specifications¶
Format Rules (Canonical JSON)¶
| Rule | Requirement |
|---|---|
| 1 line = 1 parameter | Follow function signature order |
| JSON literal | Each line is a valid JSON value |
No spaces after , | [1,2,3] not [1, 2, 3] |
| Double quotes only | "abc" not 'abc' |
| Lowercase booleans | true/false not True/False |
π See Test File Format for complete format specification.
Common Formats¶
Single array:
Array + target:
Two arrays:
Matrix (grid):
String parameter:
Single integer:
Using json.dumps for Serialization¶
import json
def _generate_case() -> str:
nums = [3, 2, 2, 3]
val = 3
# Use separators to avoid spaces
return f"{json.dumps(nums, separators=(',', ':'))}\n{val}"
# Output: "[3,2,2,3]\n3"
β οΈ Avoid manual string formatting:
# Wrong: has spaces
f"{nums}" # -> "[1, 2, 3]"
# Correct: use json.dumps
json.dumps(nums, separators=(',', ':')) # -> "[1,2,3]"
JUDGE_FUNC Requirement¶
Why JUDGE_FUNC is Required¶
Generated test cases have no expected output (.out file). The solution MUST validate correctness using JUDGE_FUNC:
π See JUDGE_FUNC Specification for complete documentation.
Generator-Specific Considerations¶
When JUDGE_FUNC is used with generators (judge-only mode):
| Parameter | Value | Implication |
|---|---|---|
actual | Solution output | Parsed via ast.literal_eval() if valid |
expected | None | No .out file exists |
input_data | Raw input string | Use to validate correctness |
The JUDGE_FUNC MUST be able to validate using only actual and input_data when expected is None.
Example Pattern¶
def judge(actual, expected, input_data: str) -> bool:
# Parse input to understand problem constraints
n = int(input_data.strip())
# Validate actual output against problem requirements
if not _is_valid_output(actual, n):
return False
# For judge-only mode: use known answers or algorithmic validation
if expected is None:
return _validate_without_expected(actual, n)
# For static tests: compare with expected
return actual == expected
JUDGE_FUNC = judge
Running Generated Tests¶
Command Line Usage¶
# Static tests + N generated tests
python runner/test_runner.py {problem} --generate N
# Only generated tests (skip static tests)
python runner/test_runner.py {problem} --generate-only N
# Reproducible with seed
python runner/test_runner.py {problem} --generate N --seed 12345
# Save failing cases to tests/
python runner/test_runner.py {problem} --generate N --save-failed
# Complexity estimation
python runner/test_runner.py {problem} --estimate
π See Test Runner Specification for full CLI reference.
Output Format¶
============================================================
π§ͺ Test Results: 0001_two_sum
============================================================
π Static Tests:
0001_two_sum_1: β
PASS [judge] 0.12ms
0001_two_sum_2: β
PASS [judge] 0.08ms
π² Generated Tests (seed=12345):
gen_1: β
PASS [judge-only] 0.45ms
gen_2: β
PASS [judge-only] 0.52ms
gen_3: β FAIL [judge-only] 0.38ms
ββ Input βββββββββββββββββββββββββββββββββ
β 5,3,8,1,2
β 11
ββββββββββββββββββββββββββββββββββββββββββ
π‘ To reproduce: python runner/test_runner.py 0001 --generate 3 --seed 12345
============================================================
Failure Reproduction¶
When a generated test fails:
-
Re-run with same seed:
-
Save failed case:
-
Debug specific case:
Best Practices¶
Generator Checklist¶
- Docstring with LeetCode constraints
-
seedparameter for reproducibility - Edge cases yielded first
- Random cases respect constraints
- Input format matches
.infiles - Solution has
JUDGE_FUNCdefined -
generate_for_complexity()if using--estimate
Performance Considerations¶
| Consideration | Recommendation |
|---|---|
| Generation speed | Keep generators fast (< 1ms per case) |
| Constraint limits | Use LeetCode max constraints for stress tests |
| Practical limits | Don't exceed O(N!) or exponential complexity bounds |
Testing Your Generator¶
# Manual test
from generators.{problem} import generate
for i, test_input in enumerate(generate(count=5, seed=42)):
print(f"--- Case {i+1} ---")
print(test_input)
print()
Quick Reference¶
Generator Template¶
# generators/{problem_id}_{slug}.py
"""
Test Case Generator for Problem {ID} - {Title}
LeetCode Constraints:
- {constraints}
"""
import json
import random
from typing import Iterator, Optional
def generate(count: int = 10, seed: Optional[int] = None) -> Iterator[str]:
if seed is not None:
random.seed(seed)
# Edge cases (store as data structures)
edge_cases = [
([1, 2, 3], 4), # example: (nums, target)
]
for nums, target in edge_cases:
yield f"{json.dumps(nums, separators=(',', ':'))}\n{target}"
count -= 1
if count <= 0:
return
# Random cases
for _ in range(count):
yield _generate_case()
def _generate_case() -> str:
# Generate valid input using json.dumps
nums = [random.randint(1, 100) for _ in range(10)]
target = random.randint(1, 200)
return f"{json.dumps(nums, separators=(',', ':'))}\n{target}"
def generate_for_complexity(n: int) -> str:
return _generate_case_with_size(n)
CLI Reference¶
# Run with generation
python runner/test_runner.py {problem} --generate N
python runner/test_runner.py {problem} --generate-only N
python runner/test_runner.py {problem} --generate N --seed S
python runner/test_runner.py {problem} --generate N --save-failed
# Complexity estimation
python runner/test_runner.py {problem} --estimate
π See Test Runner Specification for full CLI reference.
Related Documentation¶
| Document | Content |
|---|---|
| Test File Format | Canonical .in/.out format specification |
| Solution Contract | SOLUTIONS, JUDGE_FUNC, COMPARE_MODE, file structure |
| Test Runner Specification | CLI options, output format, troubleshooting |
| Architecture Migration | Polymorphic pattern migration guide |