Quick Start
Quick Start
Section titled “Quick Start”This guide walks you through writing your first scaf test file. We’ll test a simple user lookup query.
Prerequisites
Section titled “Prerequisites”- scaf CLI installed (Installation)
- A running Neo4j database (or other supported database)
- A
.scaf.yamlconfig file
Your First Test File
Section titled “Your First Test File”-
Create the test file
Create
users.scaf:// Define the query we want to testfn GetUser `MATCH (u:User {id: $userId})RETURN u.name, u.email, u.age` -
Add global setup
Set up test data that all tests will use:
setup `MATCH (n) DETACH DELETE nCREATE (alice:User {id: 1, name: "Alice", email: "alice@example.com", age: 30})CREATE (bob:User {id: 2, name: "Bob", email: "bob@example.com", age: 25})`teardown `MATCH (n) DETACH DELETE n` -
Write your first test
GetUser {test "finds Alice by id" {// Input parameter$userId: 1// Expected outputsu.name: "Alice"u.email: "alice@example.com"u.age: 30}} -
Run the test
Terminal window scaf test users.scaf
Complete Example
Section titled “Complete Example”Here’s the full file:
// Query definitionsfn GetUser `MATCH (u:User {id: $userId})RETURN u.name, u.email, u.age`
fn CountUsers `MATCH (u:User)RETURN count(u) as count`
// Global setup - runs once before all testssetup `MATCH (n) DETACH DELETE nCREATE (alice:User {id: 1, name: "Alice", email: "alice@example.com", age: 30})CREATE (bob:User {id: 2, name: "Bob", email: "bob@example.com", age: 25})`
// Global teardown - runs after all teststeardown `MATCH (n) DETACH DELETE n`
// Test scope for GetUser queryGetUser { test "finds Alice by id" { $userId: 1
u.name: "Alice" u.email: "alice@example.com" u.age: 30 }
test "finds Bob by id" { $userId: 2
u.name: "Bob" u.age: 25 }
test "returns null for non-existent user" { $userId: 999
u.name: null u.email: null }}
// Test scope for CountUsers queryCountUsers { test "counts all users" { count: 2 }}Adding Groups
Section titled “Adding Groups”Organize related tests with groups:
GetUser { group "existing users" { test "finds Alice" { $userId: 1 u.name: "Alice" }
test "finds Bob" { $userId: 2 u.name: "Bob" } }
group "edge cases" { test "missing user" { $userId: 999 u.name: null }
test "invalid id type" { $userId: -1 u.name: null } }}Adding Assertions
Section titled “Adding Assertions”For complex validations, use assert blocks:
GetUser { test "user is a verified adult" { $userId: 1
u.name: "Alice"
// Expression assertions assert { (u.age >= 18) (u.email contains "@") } }
test "verify user count with query" { $userId: 1
u.name: "Alice"
// Query assertion - runs a separate query assert CountUsers() { count == 2 } }}Test-Level Setup
Section titled “Test-Level Setup”Add setup specific to individual tests:
CountUsers { test "counts base users" { count: 2 }
test "counts with temp user" { // This setup only runs for this test setup ` CREATE (:User {id: 999, name: "Temp"}) `
count: 3 }
test "temp user was rolled back" { // Previous test's setup was in a transaction that rolled back count: 2 }}Running Tests
Section titled “Running Tests”# Run all .scaf files in current directoryscaf test
# Run specific filescaf test users.scaf
# Run files matching patternscaf test ./queries/*.scaf# Dots (default) - minimal outputscaf test --format=dots
# Verbose - full test namesscaf test --format=verbose
# JSON - machine-readable for toolingscaf test --format=json# Run tests matching a patternscaf test --run="GetUser/existing"
# Stop on first failurescaf test --fail-fastUnderstanding Output
Section titled “Understanding Output”$ scaf test users.scaf
.....5 passed, 0 failed, 0 skipped (0.05s)With verbose output:
$ scaf test users.scaf --format=verbose
GetUser/finds Alice by id ... passed (0.01s)GetUser/finds Bob by id ... passed (0.01s)GetUser/returns null for non-existent user ... passed (0.01s)CountUsers/counts all users ... passed (0.01s)CountUsers/counts with temp user ... passed (0.01s)
5 passed, 0 failed, 0 skipped (0.05s)When a test fails:
$ scaf test users.scaf --format=verbose
GetUser/finds Alice by id ... FAILED (0.01s) field: u.name expected: "Wrong Name" actual: "Alice"
0 passed, 1 failed, 0 skipped (0.02s)Next Steps
Section titled “Next Steps”- DSL Overview — Full syntax reference
- Tests & Groups — Advanced test organization
- Assertions — Expression-based validations
- Editor Integration — Set up syntax highlighting