dream_test/gherkin/discover
Discover and load Gherkin .feature files.
Use this module to:
- find
.featurefiles via a glob pattern - parse them (
load) for inspection, or - convert them into runnable
TestSuites (to_suite) when you provide a step registry (your Given/When/Then handlers).
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 valueserrors: 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.featurefiles
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: aFeatureDiscoverycreated withfeatures
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: aFeatureDiscoverycreated withfeatures
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: aFeatureDiscoverywith a registry attached viawith_registrysuite_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: aFeatureDiscoverycreated withfeaturesregistry: step definitions used to execute scenarios
Returns
The updated discovery.