cquill/testing

Types

A test context containing a memory store and tracking information.

The test context provides:

  • A fresh memory store for database operations
  • An auto-incrementing ID counter for generating unique IDs
  • Tracking of inserted entities for verification
pub type TestContext {
  TestContext(
    store: memory.MemoryStore,
    id_counter: Int,
    inserted: dict.Dict(String, List(String)),
  )
}

Constructors

  • TestContext(
      store: memory.MemoryStore,
      id_counter: Int,
      inserted: dict.Dict(String, List(String)),
    )

    Arguments

    store

    The memory store for database operations

    id_counter

    Counter for generating unique IDs in factories

    inserted

    Tracks inserted entity IDs by table name for verification

Values

pub fn create_tables(
  store: memory.MemoryStore,
  tables: List(#(String, String)),
) -> memory.MemoryStore

Create multiple tables in the memory store.

Each table is specified as a tuple of (table_name, primary_key_column). This is a convenience function for setting up test fixtures.

Example

let store = create_tables(store, [
  #("users", "id"),
  #("posts", "id"),
  #("comments", "id"),
])
pub fn get_store(ctx: TestContext) -> memory.MemoryStore

Get the memory store from a test context.

Example

let store = get_store(ctx)
let result = memory.get_row(store, "users", "1")
pub fn get_tracked(
  ctx: TestContext,
  table: String,
) -> List(String)

Get all tracked entity keys for a table.

Example

let keys = get_tracked(ctx, "users")
// Returns ["2", "1"] (most recent first)
pub fn new_context() -> TestContext

Create a new test context with a fresh memory store.

Example

let ctx = new_context()
// ctx.id_counter starts at 1
pub fn next_id(ctx: TestContext) -> #(TestContext, Int)

Generate the next unique ID for test data. Returns the updated context and the new ID.

IDs start at 1 and increment with each call.

Example

let #(ctx, id1) = next_id(ctx)
let #(ctx, id2) = next_id(ctx)
// id1 = 1, id2 = 2
pub fn next_ids(
  ctx: TestContext,
  count: Int,
) -> #(TestContext, List(Int))

Batch generate unique IDs.

Example

let #(ctx, ids) = next_ids(ctx, 3)
// ids = [1, 2, 3]
pub fn reset(ctx: TestContext) -> TestContext

Reset a test context, clearing all data but preserving table structure.

Useful for running multiple scenarios within the same test.

Example

// After first scenario
let ctx = reset(ctx)
// Tables still exist but are empty, ID counter resets to 1
pub fn set_store(
  ctx: TestContext,
  store: memory.MemoryStore,
) -> TestContext

Update the memory store in a test context.

Use this after performing operations that return a new store.

Example

let assert Ok(new_store) = memory.create_table(ctx.store, "users", [])
let ctx = set_store(ctx, new_store)
pub fn track_insert(
  ctx: TestContext,
  table: String,
  key: String,
) -> TestContext

Track an inserted entity key for later verification or cleanup.

This is useful for tracking what entities were created during a test so you can verify they exist or clean them up.

Example

let ctx = track_insert(ctx, "users", "1")
let ctx = track_insert(ctx, "users", "2")
tracked_count(ctx, "users")  // Returns 2
pub fn tracked_count(ctx: TestContext, table: String) -> Int

Get the count of tracked entities for a table.

Example

let count = tracked_count(ctx, "users")
// Returns number of entities tracked for "users" table
pub fn unique_email(ctx: TestContext) -> #(TestContext, String)

Generate a unique email for test data.

Convenience function that generates emails like “test_1@example.com”.

Example

let #(ctx, email1) = unique_email(ctx)
let #(ctx, email2) = unique_email(ctx)
// email1 = "test_1@example.com"
// email2 = "test_2@example.com"
pub fn unique_string(
  ctx: TestContext,
  prefix: String,
  suffix: String,
) -> #(TestContext, String)

Generate a unique string for test data (useful for emails, usernames, etc.)

Combines prefix, unique ID, and suffix to create unique values.

Example

let #(ctx, email) = unique_string(ctx, "user", "@example.com")
// email = "user_1@example.com"

let #(ctx, username) = unique_string(ctx, "testuser", "")
// username = "testuser_2"
pub fn unique_username(
  ctx: TestContext,
) -> #(TestContext, String)

Generate a unique username for test data.

Example

let #(ctx, username) = unique_username(ctx)
// username = "user_1"
pub fn with_context(test_fn: fn(TestContext) -> a) -> a

Run a test function with a fresh test context.

The context provides additional utilities like ID generation and entity tracking beyond what the raw memory store provides.

Example

pub fn multi_entity_test() {
  use ctx <- with_context()

  let #(ctx, user_id) = next_id(ctx)
  let #(ctx, email) = unique_email(ctx)
  // ... test code using the context
}
pub fn with_memory_store(
  test_fn: fn(memory.MemoryStore) -> a,
) -> a

Run a test function with a fresh memory store.

This is the recommended way to write tests that need a memory store. Each test gets a completely fresh store, ensuring test isolation.

Example

pub fn insert_user_test() {
  use store <- with_memory_store()

  let assert Ok(store) = memory.create_table(store, "users", [])
  // ... test code
}
Search Document