@probitas/runner

Test execution and orchestration engine for Probitas scenarios.

This package provides the ScenarioRunner class that executes scenario definitions built with @probitas/builder. It handles the complete test lifecycle including resource initialization, setup/cleanup hooks, step execution with retry logic, and result reporting.

Package Description
@probitas/builder Build scenario definitions to execute
@probitas/scenario Core type definitions
@probitas/reporter Output formatters for results
@probitas/cli CLI that uses this runner

Key Features

  • Concurrent execution: Run multiple scenarios in parallel with configurable concurrency
  • Failure control: Stop after N failures or continue through all tests
  • Resource lifecycle: Automatic initialization and disposal of resources
  • Retry logic: Built-in retry with linear/exponential backoff strategies
  • Reporter integration: Pluggable reporters for custom output formatting
  • Abort support: Cancel running tests via AbortSignal

Core Exports

  • ScenarioRunner - Main class for executing scenarios
  • Skip - Exception class to skip scenarios conditionally
  • Reporter - Interface for observing test execution events
  • RunOptions - Configuration options for test runs
  • RunResult - Aggregated results from a test run
  • ScenarioResult - Result from executing a single scenario
  • StepResult - Result from executing a single step

Error Types

Installation

deno add jsr:@probitas/runner

Classes

class

#Runner

class Runner

Top-level test runner that orchestrates execution of multiple scenarios.

The Runner manages:

  • Parallel execution with concurrency control (maxConcurrency)
  • Early stopping on failures (maxFailures)
  • Test lifecycle events through the Reporter interface
  • Aggregated results in RunResult
Examples
const reporter = new ListReporter();
const runner = new Runner(reporter);

const result = await runner.run(scenarios, {
  maxConcurrency: 4,
  maxFailures: 1,
});
NameDescription
run()Execute all scenarios and return aggregated results.
Constructor
new Runner(reporter: Reporter)

Create a new Runner with the given reporter.

Methods
run(): unknown

Execute all scenarios and return aggregated results.

Emits events through the Reporter:

  1. onRunStart - Before execution starts
  2. For each scenario (concurrently):
    • Delegates to ScenarioRunner for scenario-level execution
    • ScenarioRunner emits scenario and step level events
  3. onRunEnd - After all scenarios complete with RunResult

Interfaces

interface

#Reporter

interface Reporter
NameDescription
onRunStart()Called when the test run starts, before any scenarios execute.
onRunEnd()Called when test run completes
onScenarioStart()Called when a scenario begins execution.
onScenarioEnd()Called when scenario completes
onStepStart()Called when step starts
onStepEnd()Called when step completes (passed, failed, or skipped).
Methods
onRunStart(scenarios: readonly ScenarioDefinition[]): void | Promise<void>

Called when the test run starts, before any scenarios execute.

Parameters
onRunEnd(scenarios: readonly ScenarioDefinition[], result: RunResult): void | Promise<void>

Called when test run completes

Parameters
onScenarioStart(scenario: ScenarioDefinition): void | Promise<void>

Called when a scenario begins execution.

Parameters
onScenarioEnd(scenario: ScenarioDefinition, result: ScenarioResult): void | Promise<void>

Called when scenario completes

Parameters
onStepStart(scenario: ScenarioDefinition, step: StepDefinition): void | Promise<void>

Called when step starts

Parameters
onStepEnd(scenario: ScenarioDefinition, step: StepDefinition, result: StepResult): void | Promise<void>

Called when step completes (passed, failed, or skipped).

The result contains status-specific information:

  • If status is "passed": contains value from step execution
  • If status is "failed" or "skipped": contains error information
Parameters
interface

#RunFilter

interface RunFilter

Filter configuration for selecting scenarios to run.

Allows filtering scenarios by tags and/or name pattern. Both conditions must match if both are specified (AND logic).

Examples

Filter by tags

const filter: RunFilter = {
  tags: ["api", "integration"]  // Must have BOTH tags
};

Filter by name pattern

const filter: RunFilter = {
  pattern: /login/i  // Name must contain "login"
};
NameDescription
tagsTags that scenarios must have (all must match)
patternPattern to match against scenario name
Properties
  • readonlytags?readonly string[]

    Tags that scenarios must have (all must match)

  • readonlypattern?string | RegExp

    Pattern to match against scenario name

interface

#RunOptions

interface RunOptions

Configuration options for the scenario runner.

Controls execution behavior including concurrency, failure handling, and reporting.

Examples

Sequential execution with fail-fast

const options: RunOptions = {
  reporter: new ListReporter(),
  maxConcurrency: 1,  // Run one at a time
  maxFailures: 1      // Stop after first failure
};

Parallel execution with limit

const options: RunOptions = {
  reporter: new DotReporter(),
  maxConcurrency: 4   // Run up to 4 scenarios at once
};
NameDescription
maxConcurrencyMaximum number of scenarios to run in parallel.
maxFailuresMaximum number of failures before stopping the run.
signalAbort signal for external cancellation.
Properties
  • readonlymaxConcurrency?number

    Maximum number of scenarios to run in parallel.

    • undefined or 0: Unlimited (all scenarios run in parallel)
    • 1: Sequential execution (one at a time)
    • n: Run up to n scenarios concurrently
  • readonlymaxFailures?number

    Maximum number of failures before stopping the run.

    • undefined: Continue all scenarios regardless of failures
    • 1: Fail-fast (stop immediately on first failure)
    • n: Stop after n failures
  • readonlysignal?AbortSignal

    Abort signal for external cancellation.

    When aborted, running scenarios complete but no new ones start.

interface

#RunResult

interface RunResult

Summary of all scenario executions in a test run.

Provides aggregate statistics and detailed results for the entire run. Passed to Reporter.onRunEnd after all scenarios complete.

Examples
const summary: RunResult = {
  total: 10,
  passed: 8,
  failed: 1,
  skipped: 1,
  duration: 5432,
  scenarios: [...]
};

console.log(`${summary.passed}/${summary.total} passed`);
// → "8/10 passed"
NameDescription
totalTotal number of scenarios in the run
passedNumber of scenarios that passed
failedNumber of scenarios that failed
skippedNumber of scenarios that were skipped
durationTotal execution time in milliseconds
scenariosDetailed result for each scenario
Properties
  • readonlytotalnumber

    Total number of scenarios in the run

  • readonlypassednumber

    Number of scenarios that passed

  • readonlyfailednumber

    Number of scenarios that failed

  • readonlyskippednumber

    Number of scenarios that were skipped

  • readonlydurationnumber

    Total execution time in milliseconds

  • readonlyscenariosreadonly ScenarioResult[]

    Detailed result for each scenario

interface

#ScenarioContext

interface ScenarioContext

Runtime context for scenario execution.

Provides access to scenario metadata, accumulated results, shared storage, and resources during scenario execution. This is the "live" counterpart to the static ScenarioDefinition.

Examples

Accessing context in a step

scenario("Context Example")
  .step("Use context", (ctx) => {
    console.log(`Running: ${ctx.name}`);
    console.log(`Tags: ${ctx.options.tags.join(", ")}`);
    console.log(`Previous results: ${ctx.results.length}`);
  })
  .build();
NameDescription
nameHuman-readable scenario name
tags
resultsArray of all exec step results so far
storeShared key-value storage for cross-step communication
resourcesNamed resources registered with `.resource()`
signalAbort signal (fires on timeout or manual cancellation)
Properties
  • readonlynamestring

    Human-readable scenario name

  • readonlytagsreadonly string[]
  • readonlyresultsunknown[]

    Array of all exec step results so far

  • readonlystoreMap<string, unknown>

    Shared key-value storage for cross-step communication

  • readonlyresourcesRecord<string, unknown>

    Named resources registered with .resource()

  • readonlysignal?AbortSignal

    Abort signal (fires on timeout or manual cancellation)

Type Aliases

type

#ScenarioResult

type ScenarioResult = { status: "passed"; metadata: ScenarioMetadata; duration: number; steps: readonly StepResult[] } | { status: "failed" | "skipped"; metadata: ScenarioMetadata; duration: number; steps: readonly StepResult[]; error: unknown }

Result from executing a complete scenario.

Contains the overall scenario status, timing, all step results, and any error or skip reason. Passed to reporters and included in the final RunResult.

type

#StepResult

type StepResult = { status: "passed"; metadata: StepMetadata; duration: number; value: unknown } | { status: "failed" | "skipped"; metadata: StepMetadata; duration: number; error: unknown }

Result from executing a single step.

StepResult is a discriminated union type - the fields available depend on the status:

  • "passed": Contains value (return value from step function)
  • "failed": Contains error (exception that was thrown)
  • "skipped": Contains error (skip reason)

This type design ensures type-safe field access. Reporters should check result.status to safely access status-specific fields.

Search Documentation