Cuke4Duke JavaZone 2009

Post on 14-Dec-2014

4.664 views 1 download

description

Aslak Hellesøy presents Cuke4Duke (Cucumber on the JVM) at JavaZone 2009.

Transcript of Cuke4Duke JavaZone 2009

Aslak Hellesøy - Chief Scientist

twitter.com/aslak_hellesoyaslak.hellesoy@gmail.com

A Cuke for Dukehttp://github.com/aslakhellesoy/cuke4duke

http://cukes.info/

1350 followers55000 downloads

http://www.flickr.com/photos/twose/887903401/

125 contributors1350 followers55000 downloads

http://www.flickr.com/photos/twose/887903401/

125 contributors1350 followers55000 downloads

56 wiki pages

http://www.flickr.com/photos/twose/887903401/

125 contributors1350 followers55000 downloads

40 tools56 wiki pages

http://www.flickr.com/photos/twose/887903401/

125 contributors1350 followers55000 downloads

40 tools8 screencasts

56 wiki pages

http://www.flickr.com/photos/twose/887903401/

125 contributors1350 followers55000 downloads

40 tools8 screencasts

56 wiki pages

1 bookhttp://www.flickr.com/photos/twose/887903401/

Outside-In

features

srcsubmit_guess.feature

test/java/codebreakerGameSteps.java

Feature: code-breaker submits guess In order to make time pass when I'm alone As a player I want to play the against a machine

Scenario: all correct Given the secret code is "r g y c" When I guess "r g y c" Then the mark should be "bbbb"

submit_guess.feature

GivenWhen

Then

GivenWhen

Then

GameSteps.java

package codebreaker;import cuke4duke.*;

public class GameSteps {}

features

srcsubmit_guess.feature

test/java/codebreakerGameSteps.java

$ gem install cucumber$ cucumber features

<repositories> <repository> <id>cukes</id> <url>http://cukes.info/maven</url> </repository> </repositories>

<pluginRepositories> <pluginRepository> <id>cukes</id> <url>http://cukes.info/maven</url> </pluginRepository> </pluginRepositories>

<dependencies> <dependency> <groupId>cuke4duke</groupId> <artifactId>cuke4duke</artifactId> <version>0.1.4</version> </dependency> <dependency> <groupId>org.picocontainer</groupId> <artifactId>picocontainer</artifactId> <version>2.8.3</version> </dependency> </dependencies>

<plugin> <groupId>cuke4duke</groupId> <artifactId>cuke4duke-maven-plugin</artifactId> <configuration> <jvmArgs> <jvmArg> -Dcuke4duke.objectFactory= cuke4duke.internal.java.PicoFactory </jvmArg> </jvmArgs> <cucumberArgs> <cucumberArg>${basedir}/src/test/java</cucumberArg> </cucumberArgs> <gems> <gem>cucumber:0.3.100</gem> </gems> </configuration> </plugin>

features

srcsubmit_guess.feature

test/java/codebreakerGameSteps.java

$ mvn integration-test \ -Dcucumber.installGems=true

pom.xml

Feature: code-breaker submits guess In order to make time pass when I'm alone As a player I want to play the against a machine

Scenario: all correct # features/c..s.feature:6 Given the secret code is "r g y c" # features/c..s.feature:7 When I guess "r g y c" # features/c..s.feature:8 Then the mark should be "bbbb" # features/c..s.feature:9

1 scenario (1 undefined)3 steps (3 undefined)0m0.076s

Undefined Steps

You can implement step definitions for undefined steps with these snippets:

@Given("^the secret code is \"([^\"]*)\"$")@Pendingpublic void theSecretCodeIsRGYC_(String arg1) {}

@When("^I guess \"([^\"]*)\"$")@Pendingpublic void iGuessRGYC_(String arg1) {}

@Then("^the mark should be \"([^\"]*)\"$")@Pendingpublic void theMarkShouldBeBbbb_(String arg1) {}

Snippets

GameSteps.javapackage codebreaker;import cuke4duke.*;

public class CodeBreakerSteps { @Given("^the secret code is \"([^\"]*)\"$") @Pending public void theSecretCodeIs(String code) { }

@When("^I guess \"([^\"]*)\"$") @Pending public void iGuess(String guess) { }

@Then("^the mark should be \"([^\"]*)\"$") @Pending public void theMarkShouldBe(String mark) { }}

Feature: code-breaker submits guess In order to make time pass when I'm alone As a player I want to play the against a machine

Scenario: all correct # features/c..s.feature:6 Given the secret code is "r g y c" # public void theS..(..) TODO (Cucumber::Pending) f../c..s.feature:7:in `Given the secret code is "r g y c"' When I guess "r g y c" # public void iGue..(..) Then the mark should be "bbbb" # public void theM..(..)

1 scenario (1 pending)3 steps (2 skipped, 1 pending)0m0.079s

$ mvn integration-test

Given the secret code is "r g y c" # public void codebreaker.GameSteps .theSecretCodeIs(java.lang.String)

Location

public class GameSteps { private Game game;

@Given("^the secret code is \"([^\"]*)\"$") public void theSecretCodeIs(String code) { game = new Game(code); }}

Implement Intention

Compilation failure

src/test/java/codebreaker/CodeBreakerSteps.java:[6,12] cannot find symbolsymbol : class Gamelocation: class codebreaker.CodeBreakerSteps

features

srcsubmit_guess.feature

main/java/codebreakerGame.java

test/java/codebreakerGameSteps.java

Game.java

package codebreaker; public class Game { public Game(String code) { }}

Feature: code-breaker submits guess In order to make time pass when I'm alone As a player I want to play the against a machine

Scenario: all correct # features/c..s.feature:6 Given the secret code is "r g y c" # public void theS..(..) When I guess "r g y c" # public void iGue..(..) TODO (Cucumber::Pending) f../c..s.feature:8:in `When I guess "r g y c"' Then the mark should be "bbbb" # public void theM..(..)

1 scenario (1 pending)3 steps (1 skipped, 1 pending, 1 passed)0m0.112s

$ mvn integration-test

Steps & Step Definitions

Given the secret code is "r g y c"

@Given("^the secret code is \"([^\"]*)\"$")public void theSecretCodeIs(String code) { game = new Game(code);}

Step == Method invocation

Steps & Step Definitions

Given the secret code is "r g y c"

@Given("^the secret code is \"([^\"]*)\"$")public void theSecretCodeIs(String code) { game = new Game(code);}

Feature: code-breaker submits guess In order to make time pass when I'm alone As a player I want to play the against a machine

Scenario: all correct # features/c..s.feature:6 Given the secret code is "r g y c" # public void theS..(..) When I guess "r g y c" # public void iGue..(..) Then the mark should be "bbbb" # public void theM..(..)

1 scenario (1 passed)3 steps (3 passed)0m0.121s

$ mvn integration-test

Scenario: all correct Given the secret code is "r g y c" When I guess "r g y c" Then the mark should be "bbbb"

Scenario: 2 wrong pos, 2 correct Given the secret code is "r g y c" When I guess "r g c y" Then the mark should be "bbww"

More Scenarios

Scenario: all correct # features/c..s.feature:6 Given the secret code is "r g y c" # public void theS..(..) When I guess "r g y c" # public void iGue..(..) Then the mark should be "bbbb" # public void theM..(..)

Scenario: all correct # features/c..s.feature:6 Given the secret code is "r g y c" # public void theS..(..) When I guess "r g y c" # public void iGue..(..) Then the mark should be "bbbb" # public void theM..(..) org.junit.ComparisonFailure: expected:<bb[bb]> but was:<bb[ww]> (NativeException) codebreaker/CodeBreakerSteps.java:20:in `theMarkShouldBe' features/codebreaker_submits_guess.feature:14:in `Then the mark should be "bbww"'

1 scenario (1 failed, 1 passed)3 steps (1 failed, 3 passed)0m0.121s

Time to write the

algorithm...

Scenario: all correct Given the secret code is "r g y c" When I guess "r g y c" Then the mark should be "bbbb"

Scenario: 2 wrong pos, 2 correct Given the secret code is "r g y c" When I guess "r g c y" Then the mark should be "bbww"

DRY?

Scenario Outline: submit guess Given the secret code is "<code>" When I guess "<guess>" Then the mark should be "<mark>"

Examples: | code | guess | mark | | r g y c | r g y c | bbbb | | r g y c | r g c y | bbww | | r g y c | y r g c | bwww | | r g y c | c r g y | wwww |

Scenario Outline

Gherkin

OH HAI: STUFFING MISHUN: CUCUMBR I CAN HAZ IN TEH BEGINNIN "3" CUCUMBRZ WEN I EAT "2" CUCUMBRZ DEN I HAZ "2" CUCUMBERZ IN MAH BELLY AN IN TEH END "1" CUCUMBRZ KTHXBAI!

Multiline args (String)Then aslak.hellesoy@gmail.com should get email """ Hi aslak.hellesoy@gmail.com Congratulations, Cucumberer was accepted. See you at JavaZone! """

@Then("^(.*) should get email$")public void email(String email, String body) {}

Multiline args (Tables)Given the following proposals | email | title | | aslak.hellesoy@gmail.com | Cucumber | | bryan@brynary.com | Webrat |

@Given("^the following proposals$")public void proposals(cuke4duke.Table proposals) {}

Hooks@Before

@After

Feature: Notification emails Background: Given the following proposals | email | title | | aslak.hellesoy@gmail.com | Cucumber | | bryan@brynary.com | Webrat |

Scenario: Approve all

Scenario: Reject Webrat

Background

Tagged Hooks@Before("@im_special,@me_too")

@me_tooFeature: Lorem Scenario: Ipsum Scenario: Dolor

Feature: Sit @im_special Scenario: Amet Scenario: Consec

Feature: Take over the world I want it all

@spanish @french @english Scenario: Take over Europe @spanish @english Scenario: Take over America

@english Scenario: Take over Australia

Tagged Execution

Feature: Take over the world I want it all

@spanish @french @english Scenario: Take over Europe @spanish @english Scenario: Take over America

@english Scenario: Take over Australia

cucumber -t spanish doit.feature

Tagged Execution

Feature: Take over the world I want it all

@spanish @french @english Scenario: Take over Europe @spanish @english Scenario: Take over America

@english Scenario: Take over Australia

Tagged Execution

Feature: Take over the world I want it all

@spanish @french @english Scenario: Take over Europe @spanish @english Scenario: Take over America

@english Scenario: Take over Australia

cucumber -t ~french doit.feature

Tagged Execution

FormattersPretty

ProgressProfileHTMLJUnitRerun

Your Own

Then /^I should have "(\d+)" cukes my belly$/ do |cukes|end

Ruby

GroovyThen "^I should have "(\d+)" cukes my belly$" { int cukes ->}

Scala (coming soon)Then("^I should have "(\d+)" cukes my belly$") { cukes:int =>}

Python, C#, F# (coming later - wire protocol)Flex (via FunFX) - alive and kicking!