BDD with daml-cucumber 🥒

BDD with daml-cucumber 🥒
Behavior-driven development for daml

We've been using cucumber gherkin specifications on some of our daml projects lately. They’re great for building specifications that can be read both by a human and by gherkin tooling. What we lacked, however, was a tool that allowed us to write gherkin test implementations in daml script.

We decided to create such a tool, and are pleased to announce the release of daml-cucumber 🎊. We'll get into how it works below, but first a short demonstration:

Here’s a small example (using the default skeleton daml app) of how the tool works. First, you’ll need a gherkin feature file:

Feature: Asset

  Scenario: An asset can be issued
    Given an issuer party
    When the issuer creates an asset with the issuer as the owner
    Then an asset is created owned by the issuer

Next, you’ll need to import the cucumber library for daml.

Now you can start implementing your gherkin scenario steps in daml script:

-- Given an issuer party
given_an_issuer : Cucumber Ctx ()
given_an_issuer = do
  p <- liftScript $ allocateParty "issuer"
  modify $ \ctx -> ctx { issuer = Some p }

-- When the issuer creates an asset with the issuer as the owner
issuer_creates_asset_for_self : Cucumber Ctx (ContractId M.Asset)
issuer_creates_asset_for_self = do
  Some p <- gets issuer
  assetId <- liftScript $ submit p $ createCmd M.Asset with
    issuer = p
    owner = p
    name = "TV"
  modify $ \ctx -> ctx { knownAssetId = Some assetId }
  pure assetId

-- Then an asset is created owned by the issuer
asset_owner_is_issuer : Cucumber Ctx ()
asset_owner_is_issuer = do
  Some issuer <- gets issuer
  [asset] <- liftScript $ query @M.Asset issuer
  assertMsg "Expected asset owner to be the issuer" $
    asset._2.owner == issuer

The Ctx there is scenario context that you can read from and write to as you perform steps (so that you can, e.g., store the party you created in a previous step and look it up again later).

The daml-cucumber executable allows you to run tests associated with your feature file. It will report successes, failures (with error messages), and missing steps. E.g.:

Feature: Asset

  Scenario: An asset can be issued
    Given an issuer party => OK
    When the issuer creates an asset with the issuer as the owner => OK
    Then an asset is created owned by the issuer => OK
...

Tests Passed ✅
  Features:   1 of  1 passed
  Scenarios:  8 of  8 passed
  Steps:     29 of 29 passed

You can also use daml-cucumber to generate the a daml script that can be inspected in vscode or run with daml test, in case you need to dig into why a particular test is failing.

For more information about setting up daml-cucumber, and a more detailed example, check out the github repository: GitHub - obsidiansystems/daml-cucumber: Cucumber testing for daml scripts