gleam add --dev dream_testRapid 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.
| 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 |
| 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 |
| 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 |
| 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(...)) |
| 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(), ...])
- Installation
- Quick Start
- Writing Tests
- Context-Aware Tests
- Assertions & Matchers
- Lifecycle Hooks
- Runner & Execution
- Reporters
- Snapshot Testing
- Gherkin BDD
- Utilities
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
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 totalimport 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
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
