Given, When, Then
Write composable and expressive tests with a promise-based Given-When-Then DSL for mocha.
describe 'given when then'-> Given setup When doSomething And doAnotherThing Then check
The above example is roughly equivalent to
describe 'bdd'-> beforeEach setup it 'then'-> doSomething doAnotherThing if check == false throw
Use the package with
npm install --save-dev mocha-when-then
mocha --ui mocha-when-then
For browsers include the file ./dist/browser-bundle.js
. It includes
the promise library, the es5-shim, and exposes the mocha-when-then
interface as a
UMD module. It assumes that Mocha
is defined as a global variable.
Table of contents
Assigning Variables
By passing a string to the DSL methods you can assign variables, or for
Then
, pass variables to step.
Given 'a number'-> return 0When 'more'1When 'evenMore'2Then 'more' more > @number && @evenMore > more
As you can see, the labels will be stripped of any leading 'a'. The same holds for 'an' and 'the'.
You can also pass constant values to the steps instead of functions.
Then
Assertions
In addition to executing a step, Then
also serves as a simple
assertion replacement. It will throw an error if the return value of
the given function is false
. To not prevent you from using you on
expectations it will not throw on other falsey values like null
or
undefined
.
Given 'number'5Then 'number' it == 5 # This test fails. Then 'number' it == 4
Using Promises
All functions passed to the DSL may return promises. The next step is only executed when the promise is fullfilled.
Given 'zero'-> makePromise0When 'more'makePromise1Then -> @more > @zero
You can bypass this by using the value
modifier.
Givenvalue 'promise'makePromise0Whenvalue 'promise'-> @promisethenmakePromise1Then -> expect@promisetobeapromiseandresolveto1
Recall that the Then
label specifies which assginment will be passed
to the step. If an assignment is a promise, the Then
step will be run
with the resolved value.
Whenvalue 'zero'makePromise0Then 'zero' it == 0
Structuring Your Tests
We now explain in more detail how the step DSL maps to the default BDD DSL.
The Given
function behaves like beforeEach
. The step is executed
before all tests in the current suite and all sub-suites.
Then 'number' it > 0Given 'number'5 describe 'actual value'-> Then 'number'it it == 5
Each Then
creates a test case. The runner for this test case includes
all When
steps tha precede it, up to a previous Then
.
describe 'when then'-> When computeName When computeAge Then checkName Then checkAge When computeStars Then checkStars describe 'bdd'-> it ''-> computeName computeAge checkName it ''-> computeName computeAge checkAge it ''-> computeStars checkStars
The And
function serves as an alias for the previously used keyword.
describe 'simple'-> Given name Given age Then checkName Then checkAge describe 'with "And"'-> Given name And age Then checkName And checkAge
Test Labels
Since each Then
creates a test case it has to provide a label for the
test.
If you pass a single function to Then
, the interface will inspect the
code of that function and extract the expression that is returned last.
This works well for simple tests like
# 'then this.counter == 5' Then -> @counter == 5
You can set the label explicitly by passing a string to Then
.
# 'then the counter is 5' Then 'the counter is 5'-> @counter == 5
Finally, if a given function has a label
property, it is used to
contruct the label.
= it == 5shouldEqual5.label = 'should equal 5' # 'then the counter should equal 5' Then 'the counter'shouldEqual5
This makes it perfect for use with chai-builder.
Multiple data
Not yet implemented.
GivenAny 'name' 'alice''adam''avery'Then 'name' n0== 'a' GivenAny 'number'-> i < 5 && iThen 'name' n < 5 && n >= 0