moonrockzmoonspec
v0.11.0next
You are reading the docs for main (unreleased). Go to the v0.11.0 docs.
Docs / Migrating to moonspec 0.11.0
On this page1. 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 functions

Migrating 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/main1. Install the CLI as moonspec
run moonspec gen tests -o <dir> without build rules2. Generated test files are white-box tests
use moonspec gen steps3. 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 code5. New struct fields
call feature_to_test_filename or build_rules_test_filename6. 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.0

If 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 version

moonspec 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 tests again, then delete the old *_feature_test.mbt files. If you keep both files, each scenario runs two times.

  • Keep black-box tests. Pass --test-kind test, or set it in moonspec.json5:

    {
      "test_kind": "test"
    }

    A black-box test sees only the public API of the package, so the World type and its World impl must be pub.

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:

  1. Delete the _generated/ directory, if you have it.

  2. Remove "output": "generated" from moonspec.json5, if you set it.

  3. Run moonspec gen steps again (a moonspec-steps build 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.Ctx as 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:

VariantExamples
UnexpectedEnd@a and, not, (
UnexpectedTokenand @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 ended

The 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.

Edit this page on GitHub ↗