The test block (test) ​
In traditional development, you write tests to ensure you didn't make a mistake. In Carotene, you write tests to ensure the AI doesn't make a mistake.
Because Carotene uses the @(...) Generative Operator to let the AI write your complex business logic, testing is no longer an afterthought—it is the steering wheel. The test block acts as an unbreakable mathematical contract. If the AI hallucinates the wrong math, the test fails, the build stops, and the compiler forces the AI to fix it autonomously.
1. Auto-Generated Structural Tests (Zero-Code) ​
You do not need to write tests to verify your Carotene architecture.
Because Carotene is a strictly typed blueprint, the compiler automatically generates and executes a comprehensive structural test suite based entirely on your .carrot files. Without you writing a single line of test code, Carotene automatically performs:
- Type Fuzzing (Input/Output): The test runner bombards every function with edge-case data (nulls, max integers, empty strings) to guarantee it never crashes unexpectedly and that the output perfectly matches the expected
Future<Type>. - Schema Validation: Ensures bad data correctly returns a
400 Bad Request. - RBAC (
requires): Proves unauthorized users get401or403errors. - State Machines (
flow): Proves illegal lifecycle transitions are strictly blocked. - Zero-Trust Sandbox: Proves functions cannot mutate tables without explicit
updatesorcreatesverbs.
If the architecture dictates it, the compiler automatically tests it.
2. Proofs vs. Scenarios ​
Carotene provides two distinct ways to verify the AI's logic, each serving a different architectural purpose:
ensures (Mathematical Proofs) ​
The ensures primitive lives directly on the function signature. It enforces the absolute mathematical bounds of a single function. It does not care about your database or your business use-case; it only cares that the output is mathematically valid.
If you declare ensures result >= 0.0, the compiler treats this as a hard system boundary.
Dynamic Data Injection (Fuzzing): When you run carrot generate, if a function has an ensures boundary but no explicit test blocks exist yet, the compiler will automatically attempt to "fuzz" the function. It generates hundreds of random inputs (negative numbers, extreme integers, edge cases) and feeds them into the AI's generated logic to see if it can break the ensures rule.
test (Human-Readable Scenarios) ​
The test block is designed for multi-step, human-readable business scenarios. While ensures proves the math is safe, test proves the logic is correct for your product. You use test to verify the specific outputs of your @(...) Generative Operators and deterministic rules.
The Testing Keywords ​
Carotene eliminates nested boilerplate and relies on a flat test block with standard code execution and three specialized keywords:
given: Seeds the isolated memory sandbox with starting data. You can optionally bind this to a local variable to pass directly into your functions.mocks: Intercepts a network boundary. If your functioncallsan external API,mocksprevents the request from hitting the real internet and instantly returns a designated fake value.asserts: Verifies the final state of the database, the returned values, or network side-effects.
Example: Testing the Generative Operator ​
Let's write a test for our ProcessRefund function. We need to guarantee that the AI correctly interprets our prompt: @("Calculate the prorated refund amount...") and applies the deterministic rules (like the Gold Tier fee waiver).
domain Commerce {
// Scenario A: Standard Customer (Pays the $5 fee)
test "Calculates prorated refund and deducts standard fee" {
// 1. Sandboxed Data Construction
given store.Customer { id: "cust_1", loyaltyTier: "Standard" }
given store.Order {
id: "ord_1",
customerId: customer.id,
items: [ { price: 100.0, returned: true } ]
}
// 2. Auto-Mock External Side-Effects
mocks integration.Stripe.RefundPayment -> true
// 3. Trigger the action (Standard function call)
ProcessRefund("ord_1")
// 4. Verify the AI's `@(...)` math and side-effects
asserts store.Order("ord_1").status == Refunded
// The item was $100, minus the $5 fee. If the AI returns $100, the build fails.
asserts integration.Stripe.RefundPayment.wasCalledWith(95.0)
}
// Scenario B: Gold Customer (Fee is waived)
test "Waives fee for Gold Tier customers" {
given store.Customer { id: "cust_2", loyaltyTier: "Gold" }
given store.Order {
id: "ord_2",
customerId: goldCustomer.id,
items: [ { price: 100.0, returned: true } ]
}
mocks integration.Stripe.RefundPayment -> true
ProcessRefund("ord_2")
// The $5 deterministic fee was waived to $0. Total refund should be $100.
asserts integration.Stripe.RefundPayment.wasCalledWith(100.0)
}
}3. Test-Driven Generation (TDG) ​
When you write a test block, you are engaging in Test-Driven Generation.
When you run carrot generate (or carrot build in CI), Carotene initiates an autonomous feedback loop:
- Generate: The AI reads your
@(...)operators and writes the underlying TypeScript/Go implementation. - Execute: The compiler runs the AI's generated code against your
testblocks in a completely isolated, instantly-vaporized memory sandbox. - Critique: If an
assertsstatement fails (e.g., the AI forgot to subtract the$5fee, returning100.0instead of95.0), the compiler intercepts the failure and feeds the stack trace back to the AI. - Refine: The AI autonomously rewrites the logic and tries again.
The compilation only finishes when all your tests pass green. By writing tests in Carotene, you are mathematically guaranteeing that the generated code perfectly matches your exact business requirements before a single line ever reaches production.