BDD Defined



BDD Defined

1 0


cuke-groovy-talk

Cucumber Groovy Talk

On Github marcoVermeulen / cuke-groovy-talk

Behaviour Driven Development

using Cucumber JVM and Groovy

About Me

Marco Vermeulen

  • Love Coding!
  • Worked for Shazam, Associated Newspapers, Burberry, Visa
  • Current: Equal Experts at HMRC
  • Creator of GVM (Groovy enVironment Manager)
  • Blog: Wired for Code
  • Twitter: @marcoVermeulen

About the Talk

  • BDD in a Nutshell
  • The Good and Bad of BDD
  • Cucumber as solution
  • Mini Cucumber Demo
  • Grails Cucumber Plugin
  • Sample Application
  • This talk: http://bit.ly/1uIYrEm

About the Demo

Invader Zim

  • American Cartoon
  • Created by Jhonen Vasquez
  • On Nickelodeon from March, 2001
  • Discontinued, with Cult following!
  • Theme of IMPENDING DOOM!
  • Characters: Zim and GIR
  • Available on GitHub

About the Demo

Invader Zim

Zim and GIR

BDD Defined

Straight from the horse's mouth:

#BDD in a tweet: Using examples at multiple levels to create a shared understanding and surface uncertainty to deliver software that matters

— Dan North (@tastapod) May 26, 2013

BDD in a Nutshell

Using Examples

at multiple levels

to create a shared understanding

and surface uncertainty

to deliver software

that matters!

So What?

  • Collaborate on Specifications.
  • Write Gherkin.
  • Execute Specifications.
  • Watch tests go Pending.
  • Write the Step Defs.
  • Watch tests Fail.
  • Write Application Code.
  • Watch tests Pass!

Bad Wrap

An Orphan

Marketing Hype

ATDD (Acceptance Test Driven Development)

Lost it's Zing!!!

Cucumber Misunderstood

Cucumber - the worlds most misunderstood collaboration tool: https://t.co/BolhAB9D8L

— Cucumber Pro (@cucumber_pro) March 3, 2014

Good Vibrations

TDD Evolved

Inspires Collaboration (3 Amigos)

Behaviour vs Implementation

Outside In development

Living Documentation

Abundance of Tools

Simples!

Abundance of Tools

JBehave

Concordian

Fitnesse

EasyB

Spock?

Jasmine (for JavaScript)

Cucumber

Cucumber and Gradle

Cucumber and Gradle

An Anatomy

  • Dependencies
  • JUnit Test Runner
  • Gherkin
  • Step Definitions
  • Hooks
  • Tags

Cucumber Anatomy

Dependencies

repositories {
    jcenter()
}

dependencies {
    compile 'org.codehaus.groovy:groovy:2.3.6'
    testCompile 'junit:junit:4.11'
    testCompile 'info.cukes:cucumber-groovy:1.1.8'
    testCompile 'info.cukes:cucumber-junit:1.1.8'
}

build.gradle

Cucumber Anatomy

Test Runner

import cucumber.api.CucumberOptions
import cucumber.api.junit.Cucumber
import org.junit.runner.RunWith

@RunWith(Cucumber)
@CucumberOptions(
    format=["pretty", "html:build/reports/cucumber"],
    strict=true,
    features=["features"],
    glue=["src/test/steps"]
)
public class RunCukesTest { }

src/test/groovy/RunCukeTests.groovy

Cucumber Anatomy

Gherkin

Feature: Calculate

    Scenario: Add two numbers
        Given the input "2+2"
        When the calculator is run
        Then the output should be "4"

    Scenario: Subtract two numbers
        Given the input "9-4"
        When the calculator is run
        Then the output should be "5"

src/test/cucumber/adding.feature

Cucumber Anatomy

Step Definitions

import static cucumber.api.groovy.EN.*

Given(~'^the input "([^"]*)"$') { String input ->
    //some groovy code
}

When(~'^the calculator is run$') { ->
    //some groovy code
}

Then(~'^the output should be "([^"]*)"$') { String output ->
    //some groovy code
}

src/test/cucumber/steps/add_steps.groovy

Cucumber Anatomy

Hooks

import static cucumber.api.groovy.Hooks.*

Before(){
    //some groovy code
}

After(){
    //some groovy code        
}

src/test/cucumber/support/env.groovy

Before and After each Scenario

Mini Demo

Grails Cucumber Plugin

by Martin Hauner

Plugin Portal

https://github.com/hauner/grails-cucumber

Grails Cucumber Plugin

Features

  • Convention over Configuration
  • Easy Configuration
  • No Test Runner
  • Uses Functional Test phase
  • Has Friends! (Geb, Spock, Build Test Data, Fixtures)
  • Command Line integration
  • Good IDE Support
  • Under active development

Grails Cucumber Example

  • Invader Zim Theme
  • Quote resource page
  • Walking skeleton
  • All moving parts of setup

Grails Cucumber Example

Configuration

dependencies {
    ...
    test "org.codehaus.geb:geb-junit4:0.7.2" 
    test "org.seleniumhq.selenium:selenium-chrome-driver:2.32.0" 
    test "org.seleniumhq.selenium:selenium-support:2.32.0" 
    ...
}

plugins {
    ...
    test ':cucumber:1.0.1'
    compile ':remote-control:1.5'
    ...
}

grails-app/conf/BuildConfig.groovy

Grails Cucumber Example

Configuration

cucumber {
    tags = ["~@wip"]
    features = ["test/cucumber"]
    glue = ["test/steps"]
    formats = [ "html:target/test-reports/cucumber" ]
    strict = true
}

grails-app/conf/CucumberConfig.groovy

Replaces Test Runner configuration.

Grails Cucumber Example

Gherkin Feature

Feature: Invader Quotes

  Scenario: Invader Zim quotes by Name
    Given an Invader named "Zim"
    And the Invader "Zim" says "The Earth is safe! I did it, GIR! Now let's go destroy it!"
    When a Quote is requested for "Zim"
    Then we are taken to the Quote Page
    And we see "The Earth is safe! I did it, GIR! Now let's go destroy it!"

  Scenario: Invader GIR quotes by Name
    Given an Invader named "GIR"
    And the Invader "GIR" says "Can I be a mongoose dog?"
    When a Quote is requested for "GIR"
    Then we are taken to the Quote Page
    And we see "Can I be a mongoose dog?"

test/cucumber/quote.feature

Grails Cucumber Example

Step Definitions

Given(~'^an Invader named "([^"]*)"$') { String name ->
    //persist quote
}

When(~'^a Quote is requested for "([^"]*)"$') { String name ->
    to QuotePage
}

Then(~'^we see "([^"]*)"$') { String quote ->
    def invasionQuote = page.fetchInvasionQuote()
    assert invasionQuote == quote
}

test/cucumber/steps/quote_steps.groovy

Gorm no longer supported!

Use Remote Control Plugin instead!

Use Geb!

Grails Cucumber Example

Domain Class

class Quote {
    String name
    String message
}

grails-app/domain/../Quote.groovy

Grails Cucumber Example

Geb Page

import geb.Page

class QuotePage extends Page {
    static url = "/zim-grails/invader"
    static at = { title == "Invader Zim Quotes" }

    static content = {
        quote { $("#message") }
    }

    def fetchInvasionQuote(){
        quote.text()
    }
}

test/functional/page/QuotePage.groovy

Grails Cucumber Example

Environment Hooks

import geb.binding.BindingUpdater
import geb.Browser

import static cucumber.api.groovy.Hooks.After
import static cucumber.api.groovy.Hooks.Before

System.setProperty("geb.build.baseUrl", "http://localhost:8080")

Before () {
    bindingUpdater = new BindingUpdater (binding, new Browser ())
    bindingUpdater.initialize ()
}

After () {
    bindingUpdater.remove ()
}

test/cucumber/support/env.groovy

  • Use for any long running fixture
  • Hooks run before and after each scenario
  • Like @BeforeClass and @AfterClass in JUnit

Grails Cucumber Example

Controllers

Controller
class InvaderController {
    def index(String id) {
        [quote: Quote.findByName(id)]
    }
}
URL Mapping
"/invader/$name"(controller: "invader")

Grails Cucumber Example

GSP

<%@ page contentType="text/html;charset=UTF-8" %>
<html>
<head>
    <meta name="layout" content="main"/>
    <title>Invader Zim Quotes</title>
</head>
<body>
    <blockquote class="bq1" id="message">
        <p>${quote.message}</p>
    </blockquote>
    <p class="after" id="name">--Invader ${quote.name}</p>
</body>
</html>

Conclusion

  • BDD helps us Collaborate
  • BDD helps us make software that Matters!
  • Cucumber JVM and Gradle play nicely
  • Grails Cucumber plugin Rocks!
  • BDD is lots of fun!

Thank You!!!

Q & A