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 oncedefault_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 groupdefault_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
-
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), ), )
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
-
RunRootParallelWithReporterResult( results: List(types.TestResult), completed: Int, progress_reporter: option.Option(progress.ProgressReporter), )
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.
totalis the total number of tests across all suites in the runcompletedis 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 suitesuite: the suite to executeprogress_reporter: optional progress reporter state (typicallySome(progress.new()))write: output sink for any progress output (typicallyio.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) ordercompleted: updated completed count after drivingTestFinishedeventsprogress_reporter: progress reporter state (unchanged for the built-in progress reporter)