Behavior-Driven Development for R

Write executable specifications in a natural language that describes how your code should behave. Write specifications in feature files using 'Gherkin' language and execute them using functions implemented in R. Use them as an extension to your 'testthat' tests to provide a high level description of how your code works.


cucumber

R-CMD-check Codecov testcoverage cucumber muttest CRANstatus Grandtotal Lastmonth

An implementation of the Cucumber testing framework in R.

Introduction

The package parses Gherkin documents

Feature: Addition
  Scenario: Adding 2 integers
    When I add 1 and 1
    Then the result is 2
  Scenario: Adding integer and float
    When I add 1 and 1.1
    Then the result is 2.1
  Scenario: Adding float and float
    When I add 1.1 and 1.1
    Then the result is 2.2

and uses step definitions to run the tests

when("I add {int} and {int}", function(x, y, context) {
  context$result <- x + y
  context
})

then("the result is {int}", function(expected, context) {
  expect_equal(context$result, expected)
})

when("I add {int} and {float}", function(x, y, context) {
  context$result <- x + y
})

when("I add {float} and {float}", function(x, y, context) {
  context$result <- x + y
})

then("the result is {float}", function(expected, context) {
  expect_equal(context$result, expected)
})

The building blocks of the cucumber tests are Features and Scenarios.

  • Each Feature will be treated as a separate context – their results will be reported as if they were test-*.R files, e.g. 'test-Feature: Addition.R'.
  • Each Scenario is equivalent to a testthat::test_that or testthat::it case. You get feedback on each Scenario separately. Only if all steps in a scenario are successful, the scenario is considered successful.

Run the tests with cucumber::test(). By default it uses the CucumberProgressReporter, which reports every Gherkin step as it runs:

withr::with_dir(pass_dir, {
  cucumber::test(filter = "addition")
})
Feature: Addition
  Scenario: Adding 2 integers
    v When I add 1 and 1
    v Then the result is 2
  Scenario: Adding integer and float
    v When I add 1 and 1.1
    v Then the result is 2.1
  Scenario: Adding float and float
    v When I add 1.1 and 1.1
    v Then the result is 2.2


--------------------------------------------------------------------------------
Summary
  Total: 6 | Passed: 6 | Failed: 0
--------------------------------------------------------------------------------

When a step fails, the reporter shows which step broke and why, and repeats the failing scenarios in a summary at the end:

withr::with_dir(fail_dir, {
  cucumber::test(filter = "addition")
})
Feature: Addition
  Scenario: Adding 2 integers
    v When I add 1 and 1
    v Then the result is 2
  Scenario: Adding integer and float
    v When I add 1 and 1.1
    x Then the result is 5
      Expected `context$result` to equal `expected`.
      Differences:
        `actual`: 2.1
      `expected`: 5.0
      
      Step at: setup-steps-addition.R:6
  Scenario: Adding float and float
    v When I add 1.1 and 1.1
    x Then the result is 5
      Expected `context$result` to equal `expected`.
      Differences:
        `actual`: 2.2
      `expected`: 5.0
      
      Step at: setup-steps-addition.R:6


--------------------------------------------------------------------------------
Summary
  Total: 6 | Passed: 4 | Failed: 2
--------------------------------------------------------------------------------

Failures

Feature: Addition
  Scenario: Adding integer and float
    v When I add 1 and 1.1
    x Then the result is 5
      Expected `context$result` to equal `expected`.
      Differences:
        `actual`: 2.1
      `expected`: 5.0
      
      Step at: setup-steps-addition.R:6

Feature: Addition
  Scenario: Adding float and float
    v When I add 1.1 and 1.1
    x Then the result is 5
      Expected `context$result` to equal `expected`.
      Differences:
        `actual`: 2.2
      `expected`: 5.0
      
      Step at: setup-steps-addition.R:6

Put your acceptance tests in a directory separate to your unit tests:

tests/
├── acceptance/
│   ├── setup-steps_1.R
│   ├── setup-steps_2.R
│   ├── feature_1.feature
│   ├── feature_2.feature
├── testthat/
│   ├── test-unit_test_1.R
│   ├── test-unit_test_2.R

or alongside your unit tests:

tests/
├── testthat/
│   ├── test-cucumber.R
│   ├── test-unit_test_1.R
│   ├── test-unit_test_2.R
│   ├── setup-steps_1.R
│   ├── setup-steps_2.R
│   ├── feature_1.feature
│   ├── feature_2.feature

Examples

See the examples directory to help you get started.

How it works

The .feature files are parsed and matched against step definitions.

Step functions are defined using:

  • description: a cucumber expression.
  • and an implementation function. It must have the parameters that will be matched in the description and a context parameter - an environment for managing state between steps.

If a step parsed from one of .feature files is not found, an error will be thrown.

Parameter types

Step implementations receive data from the .feature files as parameters. The values are detected via regular expressions and cast with a transformer function.

The following parameter types are available by default:

Parameter Type Description
{int} Matches integers, for example 71 or -19. Converts value with as.integer.
{float} Matches floats, for example 3.6, .8 or -9.2. Converts value with as.double.
{word} Matches words without whitespace, for example banana (but not banana split).
{string} Matches single-quoted or double-quoted strings, for example “banana split” or ‘banana split’ (but not banana split). Only the text between the quotes will be extracted. The quotes themselves are discarded.

See cucumber::define_parameter_type() how to define your own parameter types.

Supported Gherkin syntax:

  • [x] Feature
  • [x] Scenario
  • [x] Example
  • [x] Given
  • [x] When
  • [x] Then
  • [x] And
  • [x] But
  • [x] *
  • [x] Background
  • [x] Scenario Outline (or Scenario Template)
  • [x] Examples (or Scenarios)
  • [ ] Rule
  • [x] """ (Doc Strings)
  • [x] | (Data Tables)
  • [x] @ (Tags)
  • [x] # (Comments)
  • [x] Free-format text
  • [ ] Localization

Installation

To install the stable version from CRAN:

install.packages("cucumber")

Reference manual

It appears you don't have a PDF plugin for this browser. You can click here to download the reference manual.

install.packages("cucumber")

2.2.0 by Jakub Sobolewski, 15 days ago


https://github.com/jakubsob/cucumber


Report a bug at https://github.com/jakubsob/cucumber/issues


Browse source code at https://github.com/cran/cucumber


Authors: Jakub Sobolewski [aut, cre]


Documentation:   PDF Manual  


MIT + file LICENSE license


Imports checkmate, cli, dplyr, fs, glue, purrr, R6, rlang, stringr, testthat, tibble, withr

Suggests mockery, box, shinytest2, chromote, covr, knitr, rmarkdown, quarto, pkgdown, pkgload, muttest


Suggested by muttest, pslr.


See at CRAN