When given a RUNE spec (.rune file or Markdown section), generate a complete test file for the target language’s testing framework.
Input: a RUNE spec + target language/framework (or auto-detect from project). Output: a complete, runnable test file.
Auto-detect the testing framework from project files when possible. Common examples:
| Signal | Framework |
|---|---|
pytest.ini, pyproject.toml with [tool.pytest] |
pytest (Python) |
jest.config.* |
Jest (JS/TS) |
vitest.config.* |
Vitest (JS/TS) |
go.mod |
Go testing |
Cargo.toml |
Rust #[test] |
pom.xml, build.gradle |
JUnit (Java/Kotlin) |
Package.swift |
XCTest (Swift) |
mix.exs |
ExUnit (Elixir) |
*.cabal, stack.yaml |
Hspec/HUnit (Haskell) |
composer.json |
PHPUnit (PHP) |
Gemfile |
RSpec/Minitest (Ruby) |
.csproj |
xUnit/NUnit (C#) |
This list is not exhaustive. Any language with a testing framework is supported — adapt the output to the framework’s conventions. If unclear, ask the user.
Extract from the RUNE spec:
[...] into FixturesThe [...] notation in RUNE tests is shorthand for “representative data matching CONSTRAINTS.” Expand it into concrete test fixtures using the target language’s idioms.
From spec:
CONSTRAINTS:
- "coupons: list of dicts with keys code, discount_type, discount_value, expires_at"
TESTS:
- "validate_coupon('SAVE10', [...], '2025-01-15')[0] == True"
Python (pytest):
@pytest.fixture
def sample_coupons():
return [
{"code": "SAVE10", "discount_value": 10, "expires_at": "2025-12-31"},
{"code": "OLD", "discount_value": 5, "expires_at": "2024-01-01"}, # expired
]
Go:
func sampleCoupons() []Coupon {
return []Coupon{
{Code: "SAVE10", DiscountValue: 10, ExpiresAt: "2025-12-31"},
{Code: "OLD", DiscountValue: 5, ExpiresAt: "2024-01-01"}, // expired
}
}
TypeScript (Jest):
const sampleCoupons = [
{ code: "SAVE10", discountValue: 10, expiresAt: "2025-12-31" },
{ code: "OLD", discountValue: 5, expiresAt: "2024-01-01" }, // expired
];
Rules for expanding [...]:
Convert each pseudo-assertion into a test function using the target framework.
From spec:
TESTS:
- "calculate_discount(100.0, 20) == 80.0"
- "calculate_discount(-10.0, 20) raises error"
Python (pytest):
def test_discount_normal():
assert calculate_discount(100.0, 20) == 80.0
def test_discount_negative_price_raises():
with pytest.raises(ValueError, match="Price cannot be negative"):
calculate_discount(-10.0, 20)
TypeScript (Jest):
test("calculates discount for normal values", () => {
expect(calculateDiscount(100.0, 20)).toBe(80.0);
});
test("throws on negative price", () => {
expect(() => calculateDiscount(-10.0, 20)).toThrow("Price cannot be negative");
});
Go:
func TestDiscountNormal(t *testing.T) {
result, err := CalculateDiscount(100.0, 20)
if err != nil { t.Fatal(err) }
if result != 80.0 { t.Errorf("expected 80.0, got %f", result) }
}
func TestDiscountNegativePriceErrors(t *testing.T) {
_, err := CalculateDiscount(-10.0, 20)
if err == nil { t.Fatal("expected error for negative price") }
}
Rust:
#[test]
fn test_discount_normal() {
assert_eq!(calculate_discount(100.0, 20).unwrap(), 80.0);
}
#[test]
fn test_discount_negative_price_errors() {
assert!(calculate_discount(-10.0, 20).is_err());
}
Group tests by category using the target framework’s grouping mechanism:
describe() blockst.Run()mod tests with named functions@Nested classescontext blocksdescribe blocksIf the spec has EDGE_CASES, generate additional tests for each. Skip edge case tests that duplicate existing tests from the TESTS section.
Generate a complete file with:
[...] dataFollow the target language’s naming convention for test files and functions.