Dream Test logo

Dream Test

Feature-rich unit and integration testing for Gleam.

Hex.pmDocumentationLicense

Install Dream Test

gleam add --dev dream_test

Current version: 2.1.1

Why Dream Test?

Rapid application development needs testing tools that scale and support the growing needs of the application without slowing down progress. Dream test was designed to help engineers write expressive unit and integration tests for their applications using the tools and techniques they know from other ecosystems; adapted properly to gleam and the beam.

Test Styles

Feature What you get
๐Ÿงช Unit testsdescribe/group/it for organizing tests
๐Ÿฅ’ Gherkin specs.feature files or inline Gleam DSL
๐Ÿ“ธ Snapshot testing Lock in complex output without manual assertions

Assertions

Feature What you get
โ›“๏ธ Pipe-first assertions Matchers that chain and compose
๐Ÿ“ฆ Built-in matchers Equality, booleans, options, results, lists, strings, comparisons
๐ŸŽ Unwrapping matchers Option/Result matchers that unwrap for continued assertion
๐Ÿ› ๏ธ Custom matchers Write your own for your domain

Test Organization

Feature What you get
๐Ÿ”„ Lifecycle hooksbefore_all, after_all, before_each, after_each
๐Ÿ”— Context-aware tests Shared setup across tests with unit_context
๐Ÿท๏ธ Tags Filter and organize test runs

Execution

Feature What you get
โšก Parallel execution Configurable concurrency for fast runs
๐Ÿ›ก๏ธ Isolation Crashes and timeouts don't break the run
โฑ๏ธ Timeouts Per-test timeout control
๐Ÿ” Test discovery Find tests from file paths
๐Ÿšจ Exit-on-failure Fail fast for CI
๐Ÿช Runner hooks Runner-level hooks for per-test/per-suite/per-run setup and teardown
๐Ÿงฉ Suite-specific execution config Run some suites sequential/with custom timeouts in the same runner (runner.add_suites_with_config(...))

Reporting

Feature What you get
๐Ÿ“ BDD results reporter Human-readable, hierarchical output (printed at end)
๐Ÿ“Š Progress reporter Live single-line progress bar during the run
๐Ÿ“‹ JSON results reporter Machine-readable JSON (printed at end)
๐ŸŒฟ Gherkin formatting Dedicated output for feature tests

Dream Test splits reporting into:

Full Usage Guide

  1. Installation
  2. Quick Start
  3. Writing Tests
  4. Context-Aware Tests
  5. Assertions & Matchers
  6. Lifecycle Hooks
  7. Runner & Execution โ€” includes runner hooks
  8. Reporters
  9. Snapshot Testing
  10. Gherkin BDD
  11. Utilities

Unit Tests

import dream_test/matchers.{be_equal, or_fail_with, should}
import dream_test/reporters/bdd
import dream_test/reporters/progress
import dream_test/runner
import dream_test/unit.{describe, it}
import gleam/string

pub fn tests() {
  describe("String utilities", [
    it("trims whitespace", fn() {
      "  hello  "
      |> string.trim()
      |> should
      |> be_equal("hello")
      |> or_fail_with("Should remove surrounding whitespace")
    }),
  ])
}

pub fn main() {
  runner.new([tests()])
  |> runner.progress_reporter(progress.new())
  |> runner.results_reporters([bdd.new()])
  |> runner.exit_on_failure()
  |> runner.run()
}
๐Ÿงช [Tested source](examples/snippets/test/snippets/unit/quick_start.gleam) ยท ๐Ÿ“– [Guide](documentation/02-quick-start.md)

Gherkin Integration Tests

Feature: Shopping Cart
  Scenario: Adding items
    Given I have 3 items in my cart
    When I add 2 more items
    Then I should have 5 items total
import dream_test/gherkin/feature.{FeatureConfig, to_test_suite}
import dream_test/gherkin/parser
import dream_test/gherkin/steps.{type StepContext, get_int, step}
import dream_test/gherkin/world.{get_or, put}
import dream_test/matchers.{be_equal, or_fail_with, should, succeed}
import gleam/result

fn step_have_items(context: StepContext) {
  put(context.world, "cart", get_int(context.captures, 0) |> result.unwrap(0))
  Ok(succeed())
}

fn step_add_items(context: StepContext) {
  let current = get_or(context.world, "cart", 0)
  put(context.world, "cart", current + { get_int(context.captures, 0) |> result.unwrap(0) })
  Ok(succeed())
}

fn step_verify_count(context: StepContext) {
  get_or(context.world, "cart", 0)
  |> should
  |> be_equal(get_int(context.captures, 0) |> result.unwrap(0))
  |> or_fail_with("Cart count mismatch")
}

pub fn tests() {
  let steps =
    steps.new()
    |> step("I have {int} items in my cart", step_have_items)
    |> step("I add {int} more items", step_add_items)
    |> step("I should have {int} items total", step_verify_count)

  let assert Ok(feature) = parser.parse_file("test/shopping_cart.feature")
  to_test_suite(FeatureConfig(feature: feature, step_registry: steps))
}
๐Ÿงช [Tested source](examples/snippets/test/snippets/gherkin/gherkin_file.gleam) ยท ๐Ÿ“– [Guide](documentation/10-gherkin-bdd.md)

Gherkin Syntax in Gleam

import dream_test/gherkin/feature.{feature, given, scenario, then, when}
import dream_test/gherkin/steps.{type StepContext, get_int, step}
import dream_test/gherkin/world.{get_or, put}
import dream_test/matchers.{be_equal, or_fail_with, should, succeed}
import gleam/result

pub fn tests() {
  let steps =
    steps.new()
    |> step("I have {int} items", fn(ctx: StepContext) {
      put(ctx.world, "cart", get_int(ctx.captures, 0) |> result.unwrap(0))
      Ok(succeed())
    })
    |> step("I add {int} more", fn(ctx: StepContext) {
      let current = get_or(ctx.world, "cart", 0)
      put(ctx.world, "cart", current + { get_int(ctx.captures, 0) |> result.unwrap(0) })
      Ok(succeed())
    })
    |> step("I should have {int} items", fn(ctx: StepContext) {
      get_or(ctx.world, "cart", 0)
      |> should |> be_equal(get_int(ctx.captures, 0) |> result.unwrap(0))
      |> or_fail_with("Cart count mismatch")
    })

  feature("Shopping Cart", steps, [
    scenario("Adding items", [
      given("I have 3 items"),
      when("I add 2 more"),
      then("I should have 5 items"),
    ]),
  ])
}
๐Ÿงช [Tested source](examples/shopping_cart/test/features/shopping_cart.gleam) ยท ๐Ÿ“– [Guide](documentation/10-gherkin-bdd.md)
Built in Gleam, on the BEAM, by the Dream Team.