dream_test/gherkin/discover

Discover and load Gherkin .feature files.

Use this module to:

Example

import dream_test/gherkin/discover
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_server_running(context: StepContext) {
  put(context.world, "server_running", True)
  Ok(succeed())
}

fn step_empty_cart(context: StepContext) {
  put(context.world, "cart", 0)
  Ok(succeed())
}

fn step_add_items(context: StepContext) {
  let current = get_or(context.world, "cart", 0)
  let to_add = get_int(context.captures, 0) |> result.unwrap(0)
  put(context.world, "cart", current + to_add)
  Ok(succeed())
}

fn step_verify_count(context: StepContext) {
  let expected = get_int(context.captures, 0) |> result.unwrap(0)
  get_or(context.world, "cart", 0)
  |> should
  |> be_equal(expected)
  |> or_fail_with("Cart count mismatch")
}

pub fn tests() {
  // Define step handlers
  let steps =
    steps.new()
    |> step("the server is running", step_server_running)
    |> step("the cart is empty", step_empty_cart)
    |> step("I add {int} items", step_add_items)
    |> step("the cart should have {int} items", step_verify_count)

  // Discover and load all .feature files
  discover.features("test/*.feature")
  |> discover.with_registry(steps)
  |> discover.to_suite("cart_features")
}

Types

Builder for discovering and loading feature files.

Use features() to create a discovery, then chain with with_registry() and to_suite() to build a runnable TestSuite.

This is opaque so callers can’t depend on internal fields that may change.

pub opaque type FeatureDiscovery

Result of loading features, containing both successes and errors.

This is useful if you want to control how parse errors are handled rather than converting them to failing tests.

Fields

  • features: successfully parsed feature values
  • errors: parse errors as strings (typically "path: message")
pub type LoadResult {
  LoadResult(features: List(types.Feature), errors: List(String))
}

Constructors

  • LoadResult(features: List(types.Feature), errors: List(String))

Values

pub fn features(pattern pattern: String) -> FeatureDiscovery

Start discovering features matching a glob pattern.

Use Erlang’s filelib:wildcard/1 semantics (see wildcard/1 below).

Example

discover.features("test/*.feature")

Parameters

  • pattern: glob pattern used to find .feature files

Returns

A FeatureDiscovery builder you can pipe into with_registry, load, list_files, or to_suite.

pub fn list_files(
  discovery discovery: FeatureDiscovery,
) -> List(String)

Get the list of files matching the discovery pattern.

This is a pure discovery step; files are not parsed.

Example

discover.features("test/*.feature")
|> discover.list_files()
|> should
|> contain("test/cart.feature")
|> or_fail_with("expected list_files to include test/cart.feature")

Parameters

  • discovery: a FeatureDiscovery created with features

Returns

A list of file paths matching the glob pattern.

pub fn load(discovery discovery: FeatureDiscovery) -> LoadResult

Load features and return detailed results.

This does not require a step registry because it only discovers files and parses Gherkin syntax. Step definitions are only needed when you want to execute scenarios (to_suite).

Example

let result = discover.features("test/*.feature") |> discover.load()

result.features
|> should
|> have_length(1)
|> or_fail_with("expected one parsed feature")

Parameters

  • discovery: a FeatureDiscovery created with features

Returns

A LoadResult containing parsed features and any parse errors.

pub fn to_suite(
  discovery discovery: FeatureDiscovery,
  suite_name suite_name: String,
) -> types.Root(Nil)

Build a TestSuite from discovered features.

Panics if with_registry() was not called.

Parse errors are converted into failing unit tests tagged with "parse-error".

What does this produce?

The returned suite contains one test per scenario. Each test runs the scenario’s steps using the provided step registry.

Example

// Discover and load all .feature files
discover.features("test/*.feature")
|> discover.with_registry(steps)
|> discover.to_suite("cart_features")

Parameters

  • discovery: a FeatureDiscovery with a registry attached via with_registry
  • suite_name: name to show for the top-level suite/group in reports

Returns

A TestSuite(Nil) containing one test per discovered scenario, plus failing tests for any parse errors (tagged "parse-error").

pub fn with_registry(
  discovery discovery: FeatureDiscovery,
  registry registry: steps.StepRegistry,
) -> FeatureDiscovery

Attach a step registry to the discovery.

The step registry is the set of step definitions (Given/When/Then handlers) used to execute scenarios. It is required before calling to_suite.

Example

// Define step handlers
let steps =
  steps.new()
  |> step("the server is running", step_server_running)
  |> step("the cart is empty", step_empty_cart)
  |> step("I add {int} items", step_add_items)
  |> step("the cart should have {int} items", step_verify_count)

// Discover and load all .feature files
discover.features("test/*.feature")
|> discover.with_registry(steps)
|> discover.to_suite("cart_features")

Parameters

  • discovery: a FeatureDiscovery created with features
  • registry: step definitions used to execute scenarios

Returns

The updated discovery.

Search Document