dream_test/parallel

Unified Root/Node execution engine (parallel tests, sequential groups).

This module executes types.TestSuite(context) which is an alias of types.Root(context) in the unified tree model.

NOTE: This module is intentionally event-agnostic; runner composes it with reporters for live output.

Most users should not call this module directly—prefer dream_test/runner. This module is public so advanced users can embed the executor in other tooling (custom runners, IDE integrations, etc.).

Example

import dream_test/matchers.{have_length, or_fail_with, should, succeed}
import dream_test/parallel
import dream_test/unit.{describe, it}

pub fn tests() {
  describe("Parallel executor", [
    it("can run a suite and return a list of results", fn() {
      let suite =
        describe("Suite", [
          it("a", fn() { Ok(succeed()) }),
          it("b", fn() { Ok(succeed()) }),
        ])

      parallel.run_root_parallel(parallel.default_config(), suite)
      |> should
      |> have_length(2)
      |> or_fail_with("expected two results")
    }),
  ])
}

Types

Configuration for the parallel executor.

Most users should configure execution via dream_test/runner instead of calling dream_test/parallel directly.

  • max_concurrency: how many tests may run at once
  • default_timeout_ms: default per-test timeout (used when a test doesn’t specify its own timeout)

Fields

  • max_concurrency: maximum number of tests to run concurrently within a group
  • default_timeout_ms: timeout used when a test does not set its own timeout

Example

import dream_test/matchers.{have_length, or_fail_with, should, succeed}
import dream_test/parallel.{ParallelConfig}
import dream_test/unit.{describe, it}

pub fn tests() {
  let config = ParallelConfig(max_concurrency: 2, default_timeout_ms: 1000)

  describe("ParallelConfig", [
    it("can be constructed to customize execution", fn() {
      let suite =
        describe("Suite", [
          it("a", fn() { Ok(succeed()) }),
        ])

      parallel.run_root_parallel(config, suite)
      |> should
      |> have_length(1)
      |> or_fail_with("expected one result")
    }),
  ])
}
pub type ParallelConfig {
  ParallelConfig(max_concurrency: Int, default_timeout_ms: Int)
}

Constructors

  • ParallelConfig(max_concurrency: Int, default_timeout_ms: Int)

Configuration for run_root_parallel_with_reporter.

This is an advanced API intended for building custom runners that want to drive a reporter while executing a single suite.

pub type RunRootParallelWithReporterConfig(context) {
  RunRootParallelWithReporterConfig(
    config: ParallelConfig,
    suite: types.Root(context),
    progress_reporter: option.Option(progress.ProgressReporter),
    write: fn(String) -> Nil,
    total: Int,
    completed: Int,
    runner_before_each_test: List(
      fn(types.TestInfo, context) -> Result(context, String),
    ),
    runner_after_each_test: List(
      fn(types.TestInfo, context) -> Result(Nil, String),
    ),
  )
}

Constructors

Result of run_root_parallel_with_reporter.

This is returned as a semantic type (not a tuple) so callers can use named fields and avoid positional destructuring.

pub type RunRootParallelWithReporterResult {
  RunRootParallelWithReporterResult(
    results: List(types.TestResult),
    completed: Int,
    progress_reporter: option.Option(progress.ProgressReporter),
  )
}

Constructors

Values

pub fn default_config() -> ParallelConfig

Default executor configuration.

Prefer configuring these values via dream_test/runner unless you are using the executor directly.

Example

import dream_test/matchers.{have_length, or_fail_with, should, succeed}
import dream_test/parallel
import dream_test/unit.{describe, it}

pub fn tests() {
  describe("Parallel executor", [
    it("can run a suite and return a list of results", fn() {
      let suite =
        describe("Suite", [
          it("a", fn() { Ok(succeed()) }),
          it("b", fn() { Ok(succeed()) }),
        ])

      parallel.run_root_parallel(parallel.default_config(), suite)
      |> should
      |> have_length(2)
      |> or_fail_with("expected two results")
    }),
  ])
}

Parameters

None.

Returns

A ParallelConfig with sensible defaults.

pub fn run_root_parallel(
  config config: ParallelConfig,
  suite suite: types.Root(context),
) -> List(types.TestResult)

Run a single suite and return results.

This does not drive a reporter.

Example

import dream_test/matchers.{have_length, or_fail_with, should, succeed}
import dream_test/parallel
import dream_test/unit.{describe, it}

pub fn tests() {
  describe("Parallel executor", [
    it("can run a suite and return a list of results", fn() {
      let suite =
        describe("Suite", [
          it("a", fn() { Ok(succeed()) }),
          it("b", fn() { Ok(succeed()) }),
        ])

      parallel.run_root_parallel(parallel.default_config(), suite)
      |> should
      |> have_length(2)
      |> or_fail_with("expected two results")
    }),
  ])
}

Parameters

  • config: execution settings (concurrency + default timeout)
  • suite: the suite to execute

Returns

A list of TestResult values, in deterministic (declaration) order.

pub fn run_root_parallel_with_reporter(
  config config: RunRootParallelWithReporterConfig(context),
) -> RunRootParallelWithReporterResult

Run a single suite while driving a reporter.

This is used by dream_test/runner internally.

  • total is the total number of tests across all suites in the run
  • completed is how many tests have already completed before this suite

Example

import dream_test/matchers.{succeed}
import dream_test/parallel
import dream_test/types.{type TestSuite}
import dream_test/unit.{describe, it}
import gleam/option.{None}

pub fn suite() -> TestSuite(Nil) {
  describe("suite", [
    it("passes", fn() { Ok(succeed()) }),
  ])
}

fn ignore(_text: String) {
  Nil
}

pub fn main() {
  let total = 1
  let completed = 0
  let parallel_result =
    parallel.run_root_parallel_with_reporter(
      parallel.RunRootParallelWithReporterConfig(
        config: parallel.default_config(),
        suite: suite(),
        progress_reporter: None,
        write: ignore,
        total: total,
        completed: completed,
      ),
    )
  let parallel.RunRootParallelWithReporterResult(
    results: results,
    completed: completed_after_suite,
    progress_reporter: _progress_reporter,
  ) = parallel_result
  results
}

Parameters

  • config: execution settings for this suite
  • suite: the suite to execute
  • progress_reporter: optional progress reporter state (typically Some(progress.new()))
  • write: output sink for any progress output (typically io.print)
  • total: total number of tests in the overall run (across all suites)
  • completed: number of tests already completed before this suite starts

Returns

A RunRootParallelWithReporterResult containing:

  • results: this suite’s results, in deterministic (declaration) order
  • completed: updated completed count after driving TestFinished events
  • progress_reporter: progress reporter state (unchanged for the built-in progress reporter)
Search Document