Skip to content

TrustBound/dream_test

Dream Test logo

Dream Test

Feature-rich unit and integration testing for Gleam.

Hex.pm Documentation License

Install Dream Test

gleam add --dev dream_test

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 tests describe/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 hooks before_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
🧩 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:

  • Progress (during the run): runner.progress_reporter(progress.new())
  • Results (after the run): runner.results_reporters([bdd.new(), json.new(), ...])

Full Usage Guide

  1. Installation
  2. Quick Start
  3. Writing Tests
  4. Context-Aware Tests
  5. Assertions & Matchers
  6. Lifecycle Hooks
  7. Runner & Execution
  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 Β· πŸ“– Guide

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 Β· πŸ“– Guide

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 Β· πŸ“– Guide


Built in Gleam, on the BEAM, by the Dream Team.

About

A testing framework for Gleam that gets out of your way.

Resources

License

Code of conduct

Contributing

Security policy

Stars

Watchers

Forks

Sponsor this project