BDD test framework for MoonBit with Gherkin and Cucumber Expressions
Dependencies
moon add moonrockz/moonspecstruct CalcWorld { mut result : Int } derive(Default)
impl @moonspec.World for CalcWorld with configure(self, setup) {
setup.given0("a calculator", fn() { self.result = 0 })
setup.when2("I add {int} and {int}", fn(a : Int, b : Int) {
self.result = a + b
})
setup.then1("the result should be {int}", fn(n : Int) {
assert_eq!(self.result, n)
})
}
async test "Feature: Calculator" {
let feature =
#|Feature: Calculator
#| Scenario: Addition
#| Given a calculator
#| When I add 2 and 3
#| Then the result should be 5
@moonspec.run_or_fail(CalcWorld::default,
@moonspec.RunOptions::new([@moonspec.FeatureSource::Text("calc", feature)]),
)
}| Expression | MoonBit Type | StepValue Variant |
|---|---|---|
| {int} | Int | IntVal(Int) |
| {float} | Double | FloatVal(Double) |
| {double} | Double | DoubleVal(Double) |
| {long} | Int64 | LongVal(Int64) |
| {byte} | Byte | ByteVal(Byte) |
| {short} | Int | ShortVal(Int) |
| {bigdecimal} | @decimal.Decimal | BigDecimalVal(@decimal.Decimal) |
| {biginteger} | BigInt | BigIntegerVal(BigInt) |
| {string} | String | StringVal(String) |
| {word} | String | WordVal(String) |
| {} | String | AnonymousVal(String) |
setup.given0("a calculator", fn() { self.result = 0 })
setup.given1("a user named {string}", fn(name : String) { self.user = name })
setup.when2("I add {int} and {int}", fn(a : Int, b : Int) { self.result = a + b })
setup.then1("the result should be {int}", fn(n : Int) { assert_eq!(self.result, n) })
setup.step0("the system is ready", fn() { () }) // matches any keywordsetup.given1_ctx("a user named {string}", fn(name : String, ctx : Ctx) {
self.user = name
self.feature = ctx.scenario().feature_name
})struct AccountSteps { world : BankWorld }
impl @moonspec.StepLibrary for AccountSteps with steps(self) {
let defs : Array[@moonspec.StepDef] = [
@moonspec.StepDef::given1("a balance of {int}", fn(n : Int) {
self.world.balance = n
}),
]
defs[:]
}
// Compose libraries in World::configure:
setup.use_library(AccountSteps::new(self))setup.before_test_case(fn(ctx) {
println("Starting: " + ctx.scenario().scenario_name)
})
setup.after_test_case(fn(_ctx, result) {
// result: HookResult::Passed or HookResult::Failed(Array[HookError])
ignore(result)
})ctx.attach("log output", "text/plain")
ctx.attach_bytes(png_bytes, "image/png", file_name="screenshot.png")
ctx.attach_url("https://example.com/report", "text/html")| Method | Default | Description |
|---|---|---|
| parallel(Bool) | false | Enable parallel scenario execution |
| max_concurrent(Int) | 4 | Max concurrent scenarios when parallel |
| tag_expr(String) | "" | Boolean tag filter expression |
| scenario_name(String) | "" | Filter scenarios by name |
| retries(Int) | 0 | Global retry count for failed scenarios |
| dry_run(Bool) | false | Validate wiring without execution |
| skip_tags(Array[String]) | ["@skip", "@ignore"] | Tags that skip scenarios |
| add_sink(&MessageSink) | -- | Add a formatter for envelope output |
| add_formatter(sink, dest) | -- | Register formatter with output destination |
| clear_sinks() | -- | Remove all sinks and formatters |
options.add_formatter(&@format.PrettyFormatter::new(), @moonspec.Stdout)
options.add_formatter(&@format.JUnitFormatter::new(), @moonspec.File("report.xml"))opts.tag_expr("@smoke") // only @smoke
opts.tag_expr("@smoke and not @slow") // boolean operators
opts.tag_expr("@smoke or @regression") // either tagopts.retries(2) // retry failed scenarios up to 2 timesopts.dry_run(true)opts.skip_tags(["@skip", "@ignore", "@wip"]){
world: "MyWorld",
mode: "per-scenario", // or "per-feature", or per-file map
steps: { output: "steps.mbt", exclude: ["features/wip/**"] },
skip_tags: ["@skip", "@ignore"],
formatters: [
{ type: "pretty", output: "stdout" },
{ type: "junit", output: "reports/results.xml" }
]
}| Package | Description |
|---|---|
| moonrockz/moonspec | Facade -- World, Setup, Ctx, RunOptions, run, run_or_fail |
| moonrockz/moonspec/core | World, Setup, HookRegistry, StepRegistry, Ctx |
| moonrockz/moonspec/runner | Executor with tag filtering and parallel support |
| moonrockz/moonspec/format | Pretty, Messages, JUnit formatters |
| moonrockz/moonspec/codegen | Generate test files from Gherkin features |
| moonrockz/moonspec/config | Configuration parsing (moonspec.json5) |
| moonrockz/moonspec/scanner | Feature file discovery and conflict detection |
Install
Download zipBDD test framework for MoonBit with Gherkin and Cucumber Expressions
Dependencies