An automation is a program that runs when you are not looking. That makes testing less optional than it is for most code — and Skript's answer is to make the honest test so cheap that skipping it feels silly. Everything in this chapter is a one-liner in a terminal.
The three dials
You have met all three testing options; here they are as a method. Every skript run is fully determined by three things you control from the command line:
- Which rule fires —
--event lead.created - What the event carries —
--data '{"budget":50}' - What the AI says —
--score 90
Because the simulator is deterministic (same inputs, same trace, always), a command line is a test case. Save the ones that matter next to the skript, in a plain text file or a shell script, and your automation has a regression suite:
skript run triage.skript --score 90 # hot path
skript run triage.skript --score 60 # warm path
skript run triage.skript --score 10 # cold path
skript run triage.skript --score 90 --data '{"email":""}' # hot but unreachableBranch coverage, by hand and by eye
The discipline that pays: run every branch once before deploying. Trace ✓/✗ marks make coverage visible — if you have never seen a ✓ next to a condition, you have never tested that branch. Here is a rule with an easy-to-miss corner, and the run that catches it:
when a new lead arrives score it with ai if score is hot then if email is "" then create task "Find contact info for {name}" and stop reply on email "Let's talk today, {name}!"
▶ example.skript — Skode Skript · local simulation
● event: lead.created → name: Ghost · phone: +1 555 0100 · email:
⚡ score it with ai → score 90 · HOT
✓ if score is hot → yes
✓ if email is "" → yes
☑ create task "Find contact info for {name}" → created
■ stop → skript halted
✔ done in 2.1ms — 1 taskA hot lead with no email address: without that inner guard, the reply would have gone nowhere. The --data dial exists precisely to manufacture these awkward customers on demand.
Machine-readable runs
--json swaps the human trace for a structured report — the same facts as data:
skript run triage.skript --score 90 --json
The JSON carries the outcome of the run — score, heat, assignee, tags, every message with its channel and text, every task — which makes assertions trivial in any language or in CI. A typical CI step is exactly this:
skript check triage.skript || exit 1 skript run triage.skript --score 90 --json | grep -q '"assigned": "Maya"' || exit 1
check exits non-zero on any structural error, run --json exposes the outcome to your assertion tool of choice, and the whole thing needs only Node on the runner — no test framework, no fixtures, no mocks.
What the simulator guarantees — and what it cannot
Worth stating crisply, because good testing depends on knowing the boundary.
The simulator guarantees the language: parsing, variables, arithmetic, conditions, loops, functions, and the order and content of every action your program takes. If the trace shows assign to "Maya" after ✓ if score is hot, production will do exactly that in exactly that case.
It cannot guarantee the world: what production AI will score some particular lead, whether a phone number is a deliverable WhatsApp account, what a teammate does with a task. Those live outside any language. The craft is to keep the boundary clean — make the logic exhaustively tested where it is cheap (here), and keep the world-facing steps simple enough that no surprise can hide in them.
One more chapter of machinery — sharing skripts through the marketplace — and then we talk about production itself.