Test Blocks¶
Define @test: Blocks¶
A test suite is a top-level block named after the procedure it validates. Each case has a unique label and contains Python code:
@normalize_tag(tag: str) -> str:
= `tag.strip().lower()`
@test: normalize_tag:
> case: lowercases:
`assert normalize_tag("KEDI") == "kedi"`
> case: strips_whitespace:
```
result = normalize_tag(" docs ")
assert result == "docs"
```
Use a backtick line for a short statement. Use a fenced Python block for setup, multiple assertions, or control flow.
Target Procedures¶
The name after @test: identifies the procedure in reports:
@add(left: int, right: int) -> int:
= `left + right`
@test: add:
> case: positive:
`assert add(2, 3) == 5`
The suite is validation metadata; it does not invoke the target automatically. Each case must call the procedure itself when that is part of the test.
Arrange Runtime Values¶
Cases execute against the compiled Kedi runtime. They can use top-level values, custom types, imported exports, prelude helpers, and compiled procedures:
```
def canonical(value):
return value.casefold().strip()
```
[prefix] = docs
@qualified_name(name: str) -> str:
= `<prefix> + ":" + canonical(name)`
@test: qualified_name:
> case: uses_runtime_environment:
```
assert qualified_name(" API ") == "docs:api"
```
Keep setup local to a case unless it is genuinely part of the program's public runtime environment.
Assertions in Python¶
Any exception fails the case. Python assert is conventional because it keeps
the expected condition visible:
@ratio(total: int, count: int) -> float:
= `total / count`
@test: ratio:
> case: computes_fraction:
```
value = ratio(3, 2)
assert isinstance(value, float)
assert value == 1.5
```
Kedi records the exception message in the result. A failed case does not stop the remaining cases from running.
Test Execution Order¶
Suites and their cases run in source order. Each case uses the same compiled runtime, so mutations to shared Python objects can leak into later cases. Avoid order-dependent tests; construct fresh mutable data inside each case.
Test Failures¶
kedi program.kedi --test prints one line per case:
The command exits with status 1 when one or more cases fail, or when parsing,
compilation, code generation, or optimized-prompt loading fails.
CLI Test Runs¶
Run all test suites in a file:
Backend options still apply because a tested procedure may call a model:
--test cannot be combined with -c/--command; validations require a source
file. Extra CLI arguments remain available through the runtime args binding.
Cache Behavior¶
Before tests run, Kedi generates any > auto: procedures. The default
program.cache.kedi is reused. --no-cache disables reuse and removes the
temporary codegen cache after the command:
This flag does not disable response caching configured through the Python
API and does not ignore program.kedi.optimized.json. File-backed tests
load valid optimized prompt prefixes when that artifact exists, and invalid
optimization JSON fails loudly.