On this page
1. Install the CLI as moonspec2. Generated test files are white-box tests3. gen steps writes next to the step functions4. Malformed tag expressions are errors5. New struct fields6. Test file name functionsMigrating to moonspec 0.11.0
This guide tells you how to update a project from moonspec 0.10.x to 0.11.0. Most projects need only steps 1 to 3. Steps 4 to 6 apply only if your code uses the APIs that they name.
| If you... | Read |
|---|---|
installed the CLI with moon install moonrockz/moonspec/cmd/main | 1. Install the CLI as moonspec |
run moonspec gen tests -o <dir> without build rules | 2. Generated test files are white-box tests |
use moonspec gen steps | 3. gen steps writes next to the step functions |
use tag expressions (RunOptions::tag_expr, PickleFilter::with_tags, TagExpression::parse) | 4. Malformed tag expressions are errors |
build MoonspecConfig or StepFnInfo values in code | 5. New struct fields |
call feature_to_test_filename or build_rules_test_filename | 6. Test file name functions |
1. Install the CLI as moonspec
moon install names a binary after its package directory. Thus moon install moonrockz/moonspec/cmd/main installed a binary named main, and build rules that call moonspec did not find it.
The CLI is now the package moonrockz/moonspec/cmd/moonspec:
moon install moonrockz/moonspec/cmd/moonspec
moonspec version # moonspec 0.11.0If you installed the old package, remove the main binary from ~/.moon/bin, or remove the copy or link that you made with the name moonspec.
moonrockz/moonspec/cmd/main still works, but it is deprecated. It prints a notice to stderr each time it runs.
To run the CLI without an install, use moonx:
moonx moonrockz/moonspec/cmd/moonspec@0.11.0 versionmoonspec gen build --moonx writes build rules that run the CLI through moonx, so that contributors and CI need no installed CLI.
2. Generated test files are white-box tests
moonspec gen tests -o <dir> now writes <name>_feature_wbtest.mbt files. Before 0.11.0, it wrote <name>_feature_test.mbt files. A black-box test (*_test.mbt) cannot use the private World impl that gen steps generates, so those tests did not compile.
Build rules are not affected. A rule passes -o $output, and an -o value that ends in .mbt is the exact file name.
If you run gen tests -o <dir> by hand, do one of these:
Keep the new default (recommended). Run
gen testsagain, then delete the old*_feature_test.mbtfiles. If you keep both files, each scenario runs two times.Keep black-box tests. Pass
--test-kind test, or set it inmoonspec.json5:{ "test_kind": "test" }A black-box test sees only the public API of the package, so the World type and its
Worldimpl must bepub.
moonspec gen build also accepts --test-kind and test_kind.
3. gen steps writes next to the step functions
The default value of steps.output is now "alongside". gen steps writes <world>_steps_gen.mbt in the directory of the step functions, for example src/calcworld_steps_gen.mbt.
The old default, "generated", wrote _generated/<world>_steps.mbt at the module root. That directory is not part of the World type's package, and MoonBit allows the World impl only in that package, so the file did not compile. gen steps now prints a warning when the config selects "generated".
To migrate:
Delete the
_generated/directory, if you have it.Remove
"output": "generated"frommoonspec.json5, if you set it.Run
moonspec gen stepsagain (amoonspec-stepsbuild rule does this for you).
If you set steps.output to "alongside", "per-package" or a directory path, nothing changes.
The generated code also changed. Run gen steps again so that you get these changes:
A lambda that calls a raising step function has an explicit
raise.The impl has
#warnings("-unused_value"), because only tests use it.Qualified parameter types keep their package, for example
@moonspec.DataTable.A step function can take
ctx : @moonspec.Ctxas its last parameter. See Step Function Shapes.
4. Malformed tag expressions are errors
TagExpression::parse now rejects malformed input. Before 0.11.0, it accepted any input: @a and matched like @a, and @a @b ignored @b, so a bad filter ran the wrong scenarios without an error.
A malformed expression now stops run before any scenario runs, with a TagExpressionError:
| Variant | Examples |
|---|---|
UnexpectedEnd | @a and, not, ( |
UnexpectedToken | and @a, @a or or @b, (), @a @b, @a) |
UnclosedParen | (@a or @b |
To migrate, correct the tag expressions that fail. The error message shows the expression, for example:
invalid tag expression "@a and": expected a tag, `not` or `(` but the expression endedThe signature changed from raise Error to raise TagExpressionError. Code that passes the error on, or catches Error, still compiles.
5. New struct fields
Two public structs have a new field. Code that builds them with a struct literal must set the field.
@config.MoonspecConfig has test_kind : TestKind?:
let config : @config.MoonspecConfig = {
world: Some("CalcWorld"),
mode: None,
steps: None,
skip_tags: None,
formatters: None,
no_color: None,
test_kind: None, // new
}MoonspecConfig::empty() and MoonspecConfig::from_json5 set it for you.
@scanner.StepFnInfo has handler : Bool. Set it to false to keep the old behavior. true is the same as handler=true in a step attribute.
6. Test file name functions
@codegen.feature_to_test_filename now returns the white-box name by default:
@codegen.feature_to_test_filename("features/login.feature")
// 0.10: "login_feature_test.mbt"
// 0.11: "login_feature_wbtest.mbt"
@codegen.feature_to_test_filename("features/login.feature", kind=BlackBox)
// "login_feature_test.mbt"build_rules_test_filename and render_build_rules take the same optional kind (kind and test_kind). Their default results do not change.