Autotest

JSON-driven test generation for Rust


Autotest eliminates test boilerplate by generating Rust test functions from templates and JSON case definitions. Write the logic once, define test data declaratively, and let the framework produce exhaustive test suites.


Template

Write functions in a .template.rs file. Each function becomes a test generator:

fn disjoint(candidate: Particle<String>, basis: Particle<String>) -> Option<Particle<String>> { candidate.disjoint(&basis).map(|_| candidate.clone()) }

Cases

Define test data in cases.json . Each function specifies default parameters, expected returns, and individual cases that can override defaults:

{ "functions": [ { "function": "disjoint", "cases": [ { "tags": ["complete"], "parameters": {"candidate": [["a", 1], ["b", 2]], "basis": [["c", 1], ["d", 2]]}, "returns": {"()": [["a", 1], ["b", 2]]} }, { "tags": ["partial"], "parameters": {"candidate": [["a", 1], ["b", 2]], "basis": [["b", 3], ["c", 1]]}, "returns": {"()": null} }, { "tags": ["partial"], "parameters": { "candidate": [["a", 1], ["b", 2], ["c", 3]], "basis": [["a", 5], ["b", 1], ["d", 2]] }, "returns": {"()": null} }, { "tags": ["identical"], "parameters": {"candidate": [["a", 1], ["b", 2]], "basis": [["a", 1], ["b", 2]]}, "returns": {"()": null} }, { "tags": ["empty"], "parameters": {"candidate": [], "basis": [["a", 1], ["b", 2]]}, "returns": {"()": []} }, { "tags": ["empty"], "parameters": {"candidate": [["a", 1], ["b", 2]], "basis": []}, "returns": {"()": [["a", 1], ["b", 2]]} }, { "tags": ["null"], "parameters": {"candidate": [], "basis": []}, "returns": {"()": []} } ] }, { "function": "isomorphic", "cases": [ { "tags": ["small"], "parameters": {"candidate": [["a", 1], ["b", 2]], "basis": [["a", 1], ["b", 2]]}, "returns": {"()": [["a", 1], ["b", 2]]} }, { "tags": ["near"], "parameters": {"candidate": [["a", 1], ["b", 2]], "basis": [["a", 2], ["b", 1]]}, "returns": {"()": null} }, { "tags": ["orthogonal"], "parameters": {"candidate": [["a", 1], ["b", 2]], "basis": [["a", 1], ["c", 2]]}, "returns": {"()": null} }, { "tags": ["superset"], "parameters": { "candidate": [["a", 1], ["b", 2]], "basis": [["a", 1], ["b", 2], ["c", 1]] }, "returns": {"()": null} }, { "tags": ["superset"], "parameters": { "candidate": [["a", 1], ["b", 2], ["c", 1]], "basis": [["a", 1], ["b", 2]] }, "returns": {"()": null} }, { "tags": ["empty"], "parameters": {"candidate": [], "basis": []}, "returns": {"()": []} }, { "tags": ["empty"], "parameters": {"candidate": [], "basis": [["a", 1]]}, "returns": {"()": null} }, { "tags": ["empty"], "parameters": {"candidate": [["a", 1]], "basis": []}, "returns": {"()": null} }, { "tags": ["identical"], "parameters": { "candidate": [["apple", 3], ["banana", 1], ["cherry", 2], ["date", 5]], "basis": [["apple", 3], ["banana", 1], ["cherry", 2], ["date", 5]] }, "returns": {"()": [["apple", 3], ["banana", 1], ["cherry", 2], ["date", 5]]} } ] }, { "function": "joint", "cases": [ { "tags": ["joint"], "parameters": {"candidate": [["a", 1], ["b", 2]], "basis": [["b", 3], ["c", 1]]}, "returns": {"()": [["a", 1], ["b", 2]]} }, { "tags": ["multiple"], "parameters": { "candidate": [["a", 1], ["b", 2], ["c", 3]], "basis": [["a", 5], ["b", 1], ["d", 2]] }, "returns": {"()": [["a", 1], ["b", 2], ["c", 3]]} }, { "tags": ["subset"], "parameters": {"candidate": [["a", 1], ["b", 2]], "basis": [["a", 3], ["b", 4]]}, "returns": {"()": [["a", 1], ["b", 2]]} }, { "tags": ["disjoint"], "parameters": {"candidate": [["a", 1], ["b", 2]], "basis": [["c", 1], ["d", 2]]}, "returns": {"()": null} }, { "tags": ["null"], "parameters": {"candidate": [], "basis": [["a", 1], ["b", 2]]}, "returns": {"()": null} }, { "tags": ["null"], "parameters": {"candidate": [["a", 1], ["b", 2]], "basis": []}, "returns": {"()": null} }, { "tags": ["null"], "parameters": {"candidate": [], "basis": []}, "returns": {"()": null} } ] }, { "function": "subset", "cases": [ { "tags": [], "parameters": { "candidate": [["a", 1], ["b", 1]], "basis": [["a", 1], ["b", 1], ["c", 1]] }, "returns": {"()": [["a", 1], ["b", 1]]} }, { "tags": ["superset"], "parameters": { "candidate": [["a", 1], ["b", 1], ["c", 1]], "basis": [["a", 1], ["b", 1]] }, "returns": {"()": null} }, { "tags": ["empty"], "parameters": {"candidate": [], "basis": [["a", 1], ["b", 1]]}, "returns": {"()": []} }, { "tags": ["empty"], "parameters": {"candidate": [["a", 1], ["b", 1]], "basis": []}, "returns": {"()": null} }, { "tags": ["equal"], "parameters": {"candidate": [["a", 1], ["b", 1]], "basis": [["a", 1], ["b", 1]]}, "returns": {"()": [["a", 1], ["b", 1]]} }, { "tags": ["disjoint"], "parameters": {"candidate": [["x", 1], ["y", 1]], "basis": [["a", 1], ["b", 1]]}, "returns": {"()": null} } ] }, { "function": "superset", "cases": [ { "tags": ["superset"], "parameters": { "candidate": [["a", 2], ["b", 3], ["c", 1]], "basis": [["a", 1], ["b", 2]] }, "returns": {"()": [["a", 2], ["b", 3], ["c", 1]]} }, { "tags": ["equal"], "parameters": {"candidate": [["a", 1], ["b", 2]], "basis": [["a", 1], ["b", 2]]}, "returns": {"()": [["a", 1], ["b", 2]]} }, { "tags": ["missing"], "parameters": { "candidate": [["a", 1], ["b", 2]], "basis": [["a", 1], ["b", 2], ["c", 1]] }, "returns": {"()": null} }, { "tags": ["lower"], "parameters": {"candidate": [["a", 1], ["b", 2]], "basis": [["a", 2], ["b", 1]]}, "returns": {"()": null} }, { "tags": ["empty"], "parameters": {"candidate": [["a", 1], ["b", 2]], "basis": []}, "returns": {"()": [["a", 1], ["b", 2]]} }, { "tags": ["empty"], "parameters": {"candidate": [], "basis": [["a", 1]]}, "returns": {"()": null} }, { "tags": ["empty"], "parameters": {"candidate": [], "basis": []}, "returns": {"()": []} } ] } ] }

Execution

Each test run produces a cases.execution.json report. Functions are grouped with their cases, and mismatches surface as unexpected values:

pub struct Source { pub file: PathBuf, pub cases: PathBuf, }

Macro

rust_autotest_template

Compiles the template as a rust_library for IDE support. Automatically adds -A dead_code . Shared by both function and performance modules.

rust_autotest_template( name = "template", src = "particle.template.rs", deps = [ "//Molten:component", "//Molten:system", "//Molten/system/graph/symbolic:constructor", ], )
Parameter Description
src Template source file
deps Template dependencies

Modules

Function

Generates exhaustive test suites from template functions and JSON cases

Each template function is expanded into individual test cases with parameter shadowing, tag filtering, and schema validation.

more →

Performance

Regression-aware performance testing with statistical curve fitting

Measures execution time across scaling inputs, fits complexity curves, and enforces structure assertions on polynomial term ordering.

more →