Skip to content

scaf

Write database tests the way you think about them — declarative, readable, and powerful.

Declarative Tests

Define inputs, expected outputs, and assertions in a clear, readable format. No boilerplate.

Database Native

Built for database testing. Write queries in your dialect (Cypher, SQL) with full syntax highlighting.

Hierarchical Organization

Group tests by query, feature, or scenario. Inherit setup blocks. Keep things DRY.

Editor Support

Tree-sitter grammar, Neovim plugin with neotest integration, and LSP for diagnostics.

// Define your query
fn GetUser() `
MATCH (u:User {id: $userId})
RETURN u.name, u.email, u.age
`
// Global setup
setup `
CREATE (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})
`
// Test the query
GetUser {
group "existing users" {
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
// Assertion expressions
assert (u.age >= 18)
}
}
test "non-existent user returns null" {
$userId: 999
u.name: null
}
}

The pattern: Define queries, set up test data, specify inputs with $param, and declare expected outputs. Add assertion expressions for complex validations.

Simple I/O Testing

Specify $inputs and expected outputs. scaf runs the query and compares results.

Learn more →

Expression Assertions

Use expr-lang for powerful assertions: comparisons, string matching, function calls.

Learn more →

Setup Inheritance

Define setup at suite, scope, group, or test level. Child tests inherit from parents.

Learn more →

Multiple Databases

Support for Neo4j (Cypher) with PostgreSQL, MySQL, SQLite coming soon.

Learn more →

Terminal window
go install github.com/rlch/scaf/cmd/scaf@latest

Then create a .scaf.yaml config:

neo4j:
uri: bolt://localhost:7687
username: neo4j
password: password
Terminal window
# Run all tests
scaf test
# Run specific file
scaf test queries/users.scaf
# With verbose output
scaf test --format=verbose