Example stories with easyb

Stories are an easy way to capture requirements in a natural language that mirrors normal conversations.


easyb can easily work with other Java (or Groovy or anything else that runs on the JVM!) based frameworks. For example, below is an example of using easyb with Selenium.

before "start selenium", {
 given "selenium is up and running", {
  selenium = new DefaultSelenium("localhost",
    4444, "*firefox", "http://acme.racing.net/greport")

scenario "a valid person has been entered", {

 when "filling out the person form with a first and last name", {
  selenium.type("fname", "Britney")
  selenium.type("lname", "Smith")

 and "the submit link has been clicked", {

 then "the report should have a list of races for that person", {
  values = ["Mclean 1/2 Marathon", "Reston 5K", "Herndon 10K", "Leesburg 10K"]
  for(i in 0..<values.size()){
    selenium.getText("//table//tr[${(i+3)}]/td").shouldBeEqualTo values[i]

after "stop selenium" , {
 then "selenium should be shutdown", {

easyb supports the notion of narratives, which attempt to set the stage of a story. For example, below is an example of using a narrative for a story describing money.

package io.easyb.bdd.money

description "This story is about currency management"

narrative "this string is required for now", {
 as a "person who uses money"
 i want "to be able to add them together"
 so that "that I can become rich"

scenario "two moneys of the same currency are added", {

 given "one money object is added to another", {
  total = new Money(12, "CHF").add(new Money(14, "CHF"))

 then "the total amount should be the sum of the two", {
  total.amount().shouldBe 26

easyb's should syntax is quite flexible as it takes an expression. Accordingly, the example below shows an expression that validates the value of value.

scenario "easyb can and should support expressions", {

 given "a value of 3", {
  value = 3

 then "an expression should evaluate to true", {
  (value >=0 && value <=6).shouldBe true

Stories can be considered "pending" -- thus, they are not implemented. Creating a pending state is easy -- just leave the closure body unimplemented as demonstrated below.

scenario "Non-Gold level customer with $100 or more" , {
 given "a non-Gold level customer"
 when "they have $100 or more in their shopping cart"
 then "they should receive a $10 discount"
 and "they should be emailed a coupon"

scenario "another Non-Gold level customer with $100 or more" , {
 given "another non-Gold level customer"
 when "they have another $100 or more in their shopping cart"
 then "they should receive another $10 discount"
 and "they should be emailed another coupon"

easyb can easily verify that specific exceptions were generated as a result of behavior. Just use the ensureThrows clause, shown below.

import io.easyb.exception.VerificationException

scenario "ensureThrows should be less noisy", {
 given "some error condition", {
  var = {
   throw new NullPointerException("ha!")
 then "the ensureThrows clause should accept a String value rather than a class", {
  ensureThrows(NullPointerException) {

scenario "ensure strict exception handling", {
 given "something useless", {
  blah = "blah"
 then "the ensureThrows clause should be strict", {
  ensureStrictThrows(VerificationException) {
   ensureStrictThrows(RuntimeException.class) {
     throw new IllegalArgumentException("Test")