Skip to content

Imports

Imports allow you to reuse setup functions, fixtures, and test utilities across multiple scaf files.

// Import a module
import "./shared/fixtures"
// Import with alias
import fixtures "./shared/fixtures"

Paths are relative to the current file:

project/
├── queries/
│ ├── users.scaf # import "../shared/fixtures"
│ └── posts.scaf # import "../shared/fixtures"
├── shared/
│ └── fixtures.scaf # defines reusable setups
└── .scaf.yaml

After importing, use the module’s functions in setup blocks:

import fixtures "./shared/fixtures"
// Use as named setup
setup fixtures.CreateUsers()
// With parameters (no $ prefix)
setup fixtures.CreatePosts(count: 10, authorId: 1)

In your shared file, define functions that can be called as setups:

shared/fixtures.scaf
// Simple setup - no parameters
fn CreateUsers() `
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})
`
// Parameterized setup
fn CreatePosts(count: int, authorId: int) `
UNWIND range(1, $count) as i
CREATE (:Post {
id: i,
authorId: $authorId,
title: "Post " + toString(i),
createdAt: timestamp()
})
`
// Setup with relationships
fn CreateFriendships(userId: int, friendIds: [int]) `
MATCH (u1:User {id: $userId})
UNWIND $friendIds as friendId
MATCH (u2:User {id: friendId})
CREATE (u1)-[:FRIENDS_WITH]->(u2)
`
queries/users.scaf
import fixtures "../shared/fixtures"
fn GetUser(userId: string) `
MATCH (u:User {id: $userId})
RETURN u.name, u.email, u.age
`
// Suite setup using fixture
setup fixtures.CreateUsers()
GetUser {
// Scope setup with parameters (no $ prefix)
setup fixtures.CreatePosts(count: 5, authorId: 1)
group "with friends" {
// Group setup with parameters
setup fixtures.CreateFriendships(userId: 1, friendIds: [2])
test "user has friends and posts" {
$userId: 1
u.name: "Alice"
}
}
}

Use aliases to distinguish between multiple imports:

import users "./shared/user-fixtures"
import posts "./shared/post-fixtures"
import common "./shared/common"
setup common.ClearDatabase()
setup users.CreateTestUsers()
setup posts.CreateTestPosts(count: 10)

scaf resolves imports at parse time:

  1. Path is resolved relative to the importing file
  2. The imported file is parsed
  3. Function definitions become available via the alias
shared/
├── users.scaf # User fixtures
├── posts.scaf # Post fixtures
├── comments.scaf # Comment fixtures
└── common.scaf # Clear database, etc.
shared/
├── fixtures.scaf # Test data creation
├── cleanup.scaf # Teardown utilities
└── assertions.scaf # Common assertion functions
shared/
├── fixtures/
│ ├── users.scaf
│ ├── posts.scaf
│ └── index.scaf # Re-exports all
└── utils/
└── cleanup.scaf
setup fixtures.CreateUser(id: 1, name: "Alice")
setup fixtures.CreateFriendships(
userId: 1,
friendIds: [2, 3, 4, 5]
)
setup fixtures.CreateUser(
id: 1,
data: {name: "Alice", email: "alice@example.com", age: 30}
)
test "with dynamic data" {
$userId: 1
u.id: 1
// Use result value as parameter
assert fixtures.CountPosts(authorId: u.id) {
(count >= 0)
}
}
  1. Group related fixtures — Keep user fixtures together, post fixtures together, etc.

  2. Use descriptive namesCreateUserWithPosts is clearer than Setup1

  3. Parameterize when possible — Make fixtures flexible

  4. Add type annotations — Improves documentation and validation

  5. Document complex fixtures — Add comments explaining the data structure

  6. Keep fixtures focused — One responsibility per setup function

shared/fixtures.scaf
// Creates a standard test user with optional profile
// Parameters:
// id: User ID (required)
// name: Display name (required)
// withProfile: Create profile if true (optional, default false)
fn CreateUserWithProfile(id: string, name: string, withProfile: bool?) `
CREATE (u:User {id: $id, name: $name})
WITH u
FOREACH (x IN CASE WHEN $withProfile THEN [1] ELSE [] END |
CREATE (u)-[:HAS_PROFILE]->(:Profile {bio: "Hello, I am " + $name})
)
RETURN u
`

scaf reports errors for:

  • File not found
  • Circular imports
  • Invalid path syntax
  • Missing function definitions
Error: import "./shared/fixtures"
→ file not found: ./shared/fixtures.scaf
Error: circular import detected
→ a.scaf imports b.scaf imports a.scaf