dream_test/discover

Test module discovery for Dream Test.

This module provides an ergonomic way to discover test modules at runtime (compiled .beam modules) and load their tests/0 suites without having to manually import every module.

Mental model

Example

import dream_test/discover.{from_path, to_suites}
import dream_test/reporters/bdd
import dream_test/reporters/progress
import dream_test/runner.{exit_on_failure, progress_reporter, results_reporters, run}

pub fn main() {
  let suites =
    discover.new()
    |> from_path("snippets/unit/**.gleam")
    |> to_suites()

  runner.new(suites)
  |> progress_reporter(progress.new())
  |> results_reporters([bdd.new()])
  |> exit_on_failure()
  |> run()
}

Note: discovery requires compiled BEAM modules.

Types

Result of loading suites, containing both successes and errors.

This is returned by load so callers can decide how to handle errors: return them, log them, or convert them into failing suites via to_suites.

Fields

  • suites: successfully loaded suites
  • errors: discovery or load errors (human-readable strings)

Example

let discover.LoadResult(suites: suites, errors: _errors) =
  discover.tests("snippets/**.gleam")
  |> discover.load()
pub type LoadResult {
  LoadResult(suites: List(types.Root(Nil)), errors: List(String))
}

Constructors

  • LoadResult(suites: List(types.Root(Nil)), errors: List(String))

Builder for discovering test modules and loading their suites.

Discovery is built incrementally by adding one or more module-path glob patterns (see from_path / tests).

TestDiscovery is opaque: you can only build/consume it through the functions in this module.

Example

discover.tests("snippets/unit/**.gleam")
|> discover.load()
pub opaque type TestDiscovery

Values

pub fn from_path(
  discovery discovery: TestDiscovery,
  pattern pattern: String,
) -> TestDiscovery

Add a glob pattern to the discovery set.

You can call this multiple times to build up a list of globs.

Parameters

  • discovery: The current discovery builder
  • pattern: A slash-separated module path glob (the .gleam extension is optional)

Returns

A new TestDiscovery with the pattern appended.

Example

import dream_test/discover.{from_path, to_suites}
import dream_test/reporters/bdd
import dream_test/reporters/progress
import dream_test/runner.{exit_on_failure, progress_reporter, results_reporters, run}
import gleam/io

pub fn main() {
  let suites =
    discover.new()
    |> from_path("snippets/unit/**.gleam")
    |> to_suites()

  runner.new(suites)
  |> progress_reporter(progress.new())
  |> results_reporters([bdd.new()])
  |> exit_on_failure()
  |> run()
}
pub fn list_modules(
  discovery discovery: TestDiscovery,
) -> Result(List(String), String)

List module names discovered for the configured pattern.

This returns the discovered module names (as strings) or an aggregated error message if discovery failed.

Parameters

  • discovery: The configured discovery builder

Returns

  • Ok(modules): A list of discovered module names
  • Error(message): A human-readable error message (may contain multiple causes)

Example

import dream_test/discover

pub fn main() {
  discover.tests("snippets/unit/**.gleam")
  |> discover.list_modules()
}
pub fn load(discovery discovery: TestDiscovery) -> LoadResult

Load discovered suites and return both suites and errors.

This never panics; discovery errors are returned in LoadResult.errors.

Parameters

  • discovery: The configured discovery builder

Returns

A LoadResult with:

  • suites: successfully loaded TestSuite(Nil) values
  • errors: discovery or load errors (as strings)

Example

import dream_test/discover

pub fn main() {
  discover.tests("snippets/unit/**.gleam")
  |> discover.load()
}
pub fn new() -> TestDiscovery

Create an empty discovery builder.

Most users will start with tests(pattern) instead.

Returns

A new empty TestDiscovery.

Example

import dream_test/discover.{from_path, to_suites}
import dream_test/reporters/bdd
import dream_test/reporters/progress
import dream_test/runner.{exit_on_failure, progress_reporter, results_reporters, run}
import gleam/io

pub fn main() {
  let suites =
    discover.new()
    |> from_path("snippets/unit/**.gleam")
    |> to_suites()

  runner.new(suites)
  |> progress_reporter(progress.new())
  |> results_reporters([bdd.new()])
  |> exit_on_failure()
  |> run()
}
pub fn tests(pattern pattern: String) -> TestDiscovery

Start discovering tests matching a module path glob pattern.

The pattern is written using slash-separated module paths and may include * / ** globs. The .gleam extension is optional.

Examples:

  • "unit/**_test.gleam"
  • "unit/errors/**_test.gleam"
  • "dream_test/**_test.gleam"

Parameters

  • pattern: A slash-separated module path glob (the .gleam extension is optional)

Returns

A new TestDiscovery initialized with the pattern.

Example

import dream_test/discover
import dream_test/reporters/bdd
import dream_test/reporters/progress
import dream_test/runner.{exit_on_failure, progress_reporter, results_reporters, run}
import gleam/io

pub fn main() {
  let suites =
    discover.tests("snippets/unit/**.gleam")
    |> discover.to_suites()

  runner.new(suites)
  |> progress_reporter(progress.new())
  |> results_reporters([bdd.new()])
  |> exit_on_failure()
  |> run()
}
pub fn to_suite(
  discovery discovery: TestDiscovery,
  suite_name suite_name: String,
) -> types.Root(Nil)

Build a single suite from discovered suites.

Any discovery/load errors are converted into failing unit tests tagged with "discovery-error".

Parameters

  • discovery: The configured discovery builder
  • suite_name: Name to use for the outer group in the combined suite

Returns

A single TestSuite(Nil) containing:

  • all discovered suites, and
  • any errors as failing tests tagged "discovery-error".

Example

import dream_test/discover
import dream_test/reporters/bdd
import dream_test/reporters/progress
import dream_test/runner.{exit_on_failure, progress_reporter, results_reporters, run}
import gleam/io

pub fn main() {
  let suite =
    discover.tests("snippets/unit/**.gleam")
    |> discover.to_suite("discovered tests")

  runner.new([suite])
  |> progress_reporter(progress.new())
  |> results_reporters([bdd.new()])
  |> exit_on_failure()
  |> run()
}
pub fn to_suites(
  discovery discovery: TestDiscovery,
) -> List(types.Root(Nil))

Load discovered suites and return them as a list.

Any discovery/load errors are converted into failing unit tests tagged with "discovery-error", so missing coverage is visible.

Parameters

  • discovery: The configured discovery builder

Returns

A list of suites. If any errors occurred, an additional failing suite tagged "discovery-error" is appended.

Example

import dream_test/discover.{from_path, to_suites}
import dream_test/reporters/bdd
import dream_test/reporters/progress
import dream_test/runner.{exit_on_failure, progress_reporter, results_reporters, run}
import gleam/io

pub fn main() {
  let suites =
    discover.new()
    |> from_path("snippets/unit/**.gleam")
    |> to_suites()

  runner.new(suites)
  |> progress_reporter(progress.new())
  |> results_reporters([bdd.new()])
  |> exit_on_failure()
  |> run()
}
Search Document