Test-Driven in GroovyJoseph MuraskiChristopher Bartling
Joseph MuraskiIndependent Consultant in the Twin CitiesDevelop enterprise applications using Java, .Net, Groovy, Grails…Email: joe.muraski@mantacs.comTwitter: jmuraskiBlog: joemuraski.blogspot.com
Christopher BartlingIndependent consultant, based in the Twin CitiesTeach, mentor and coach for DevJamExperiences include building enterprise applications with Java, Groovy, Grails, .NET, and Adobe FlexEmail: chris.bartling@gmail.comTwitter: cbartlingBlog: bartling.blogspot.com
Goals of the workshopIntroduce features in Groovy that will help your Java testing effortsIntroduce Cucumber and cuke4duke as new tools in your testing arsenal  Demonstrate unit, integration, and acceptance testing with Groovy and Cucumber (via cuke4duke) via an example Java web applicationGet hands on with these technologies
SummaryDesign principlesTesting facilities built into GroovyAcceptance/BDD testing with Groovy	Cucumber and cuke4dukePresentation and code available  http://bitbucket.org/joe.muraski/grails_tdd_workshop/Instructions on how to use Mercurial to clone the repository or retrieve everything in an archive file
Prerequisites for hands on labsJava 1.6 JDK installationMaven 2 That’s it…Maven will take care of resolving all the other dependencies
Maven 2Maven2 installation requiredWe’re using version 2.2.1This is not a Maven presentationWe use it because it’s quite handy and does a great job of resolving dependenciesMaven commands will be presented when needed
Maven plugins usedorg.codehaus.gmaven:gmaven-plugin:1.2org.mortbay.jetty:maven-jetty-plugincuke4duke:cuke4duke-maven-plugin:0.2.4org.apache.maven.plugins:maven-surefire-plugin
Sample web applicationStarting the web appmvn jetty:run-explodedRunning testsmvn testsRunning cuke4dukemvn cuke4duke:cucumber
Design principlesSingle responsibility per class (high cohesion)Loose coupling of collaborators (low coupling)Injection of dependencies
Why Groovy?Groovy works seamlessly with JavaIt’s all just bytecode in the endGroovy offers a relaxed Java syntaxInteresting tools included in Groovy	GSQLXmlSlurper, XmlParser, BuildersGPathConvenient collectionsPrivate method testing
GroovyTestCaseIncluded in Groovy distributionExtends junit.framework.TestCaseProvides a number of helper methods for assertions Does not require test* methods to be void return typeNo need to declared throws checked exceptions in testsGroovy converts checked exceptions to unchecked exceptions
Convenience assert methodsassertArrayEquals(Object[] expected, Object[] actual)assertContains(char expected, char[] actualArray)assertContains(int expected, int[] actualArray)assertInspect(Object value, String expected)assertLength(int length, Object[] array)assertScript(String script)assertToString(Object value, String expected)
shouldFail() closuresshouldFail(Closure closure)Asserts supplied closure fails when evaluatedshouldFail(Class desiredThrownType, Closure closure)Asserts supplied closure fails when evaluated and particular exception type is thrownshouldFailWithCause(Class desiredCauseType, Closure closure)Will check for a checked exception as the root cause (checked exceptions are wrapped in Groovy)
Mocking Java classes with GroovyMap coercionGroovy’s mock libraryGMock libraryJava mocking frameworks
Map coercionAdd named closures to the mapOnly one closure can be mapped to a “method name”Cannot overload methodsCoerce to desire type using the as operator
Map coercion example
Private Method CallingGroovy can call private methodsBroken encapsulation?  Better reflection abstractions?Java can invoke private methods, it’s just more painfulIs testing private methods Good or a Smell?
Private method testing example
Groovy mocking libraryGroovy's built-in mock support does not allow us to test Java classesRelies on hooking into Groovy's object lifecycle mechanismsJava can not make call to Groovy Mock or StubUse Java mocking frameworks insteadCan cheat by putting Groovy Mock in a coerced map but why??
GMockGroovy-based mock objects frameworkEasy syntax and usageWorks when called by Java classes
GMockCreate MockAddressService service = mock(AddressService)Create Expectationservice.fetch(“id”).returns(new Address()).once()Easy Mathcingservice.save(match{it.personId == “id”}).returns(“id”).once()
GMock example
Java Mocking FrameworksJava Mocking frameworks can be used with GroovySome have minor  syntax issues or needed work arounds (JMock)Great to use if you already have one you are using and don’t want to switch
GSQLEasy to create connectionssql= Sql.newInstance("jdbc:hsqldb:hsql://localhost/", "sa", "", "org.hsqldb.jdbcDriver")Simple to work with row setssql.rows(“select * from address”).each {println “id: ${it.id}”}No try catch blocks
GSQL example
Acceptance Test-DrivenStory tests manifest themselves as executable testsDrives the development of complete featuresFrameworks are availableFit, FitLibrary, FitNessehttp://fit.c2.com/Robot Framework http://code.google.com/p/robotframework/Cucumber http://cukes.info/Others
CucumberTool for executing plain-text functional descriptions as automated testsSupports BDDCucumber tests are typically written before anything elseverified by business analysts, domain experts, non-technical stakeholders The production code is then written to make the Cucumber tests passOutside-in development
Cucumber (via cuke4duke)Cucumber for the JVMOutside-in testingFacilitates automation of acceptance/story testsFeatures and scenarios use normal languageStep definitions can be written in Groovy, as we’ll seeUses JRuby to run the core Cucumber frameworkhttp://wiki.github.com/aslakhellesoy/cuke4duke/
Cucumber featuresPurposesDocumentation of the systemAutomated, executable acceptance testsWhat code should I write next? Written in GherkinBusiness readable DSLDescribe software behavior without detailing implementationGrammar exists in different spoken languages (37 currently)Feature source files have .feature extension
Given-When-ThenScenarios consist of stepsGiven: Put the system in a known state before the user starts interacting with the system; pre-conditionsWhen: Describe the key action a user performs in this scenarioThen: Observe outcomes; observations should relate to business value of the featureUse And and But to keep features fluent
Cucumber step definitionsWritten in Groovy for our examplesCan be written in many different programming languagesAnalogous to method or function definitionStart with adjective/adverbRegular expression which will match some text from a feature(s)Take 0 or more argumentsArguments bound to regular expression groupsMulti-line step arguments
HooksBeforeExecutes before the first step of each scenarioAfterExecutes after the last step of each scenarioExecute regardless if there are failing, undefined, pending or skipped stepsAfterStepExecutes after each step in a scenario
HooksFound in Groovy files in the support directoryOur example uses one: env.groovyHooks allow us to run blocks of code at various points in the Cucumber test cycleNo association between where the hook is defined and which scenario/step it is run forAll defined hooks (one or more) are run whenever the relevant event occurs
Tagged hooksNeed to execute a certain hook for only certain scenariosAchieved by associating a Before, After or AfterStep hook with one or more tagsSee the env.groovy fileIt uses a Before hook with a @database tag to load the database via DBUnit
Tagging scenariosAllows you to group scenarios for inclusion or exclusion in a Cucumber run@wip is provided out of the boxUsing tags in cuke4duke and Maven…mvn cuke4duke:cucumber –DcukeArgs=“--tags @wip”mvn cuke4duke:cucumber -DcukeArgs=“--tags ~@wip”Inside of the Maven POM: <cucumberArg>${cukeArgs}</cucumberArg>
Running cuke4dukeThe cuke4duke Maven pluginmvn cuke4duke:cucumberFirst time: use –Dcucumber.installGems=trueAdd –o option to work offlineFeatures and step definitions are discovered by the pluginFeatures belong in features directoryStep definitions found in the step_definitions directory
cuke4duke acceptance testsStep definitions will be written in GroovyOther JVM languages are allowedUse cuke4duke.GroovyDslUse WebDriver: http://code.google.com/p/seleniumTest web UIUse DbUnit: http://www.dbunit.org/Bulk load the database with known fixture data
Acceptance testing configuration
Cucumber examples
Workshop activitiesNow it’s your turn!Try your hand at unit testing with GroovyRefactor the existing web appIntroduce DAO for database functionalityAdd services to orchestrate business logicWrite some Cucumber features and build out or reuse the Groovy step definitionsTry to add new features and practice outside-in developmentIs ATDD beneficial?  Why or why not?
Interesting resourceshttp://cukes.info/http://blog.dannorth.net/whats-in-a-story/http://blog.dannorth.net/introducing-bdd/http://www.ibm.com/developerworks/java/library/j-pg11094/http://wiki.github.com/aslakhellesoy/cucumber/
Discussion

Test Driven In Groovy

  • 1.
    Test-Driven in GroovyJosephMuraskiChristopher Bartling
  • 2.
    Joseph MuraskiIndependent Consultantin the Twin CitiesDevelop enterprise applications using Java, .Net, Groovy, Grails…Email: joe.muraski@mantacs.comTwitter: jmuraskiBlog: joemuraski.blogspot.com
  • 3.
    Christopher BartlingIndependent consultant,based in the Twin CitiesTeach, mentor and coach for DevJamExperiences include building enterprise applications with Java, Groovy, Grails, .NET, and Adobe FlexEmail: chris.bartling@gmail.comTwitter: cbartlingBlog: bartling.blogspot.com
  • 4.
    Goals of theworkshopIntroduce features in Groovy that will help your Java testing effortsIntroduce Cucumber and cuke4duke as new tools in your testing arsenal Demonstrate unit, integration, and acceptance testing with Groovy and Cucumber (via cuke4duke) via an example Java web applicationGet hands on with these technologies
  • 5.
    SummaryDesign principlesTesting facilitiesbuilt into GroovyAcceptance/BDD testing with Groovy Cucumber and cuke4dukePresentation and code available http://bitbucket.org/joe.muraski/grails_tdd_workshop/Instructions on how to use Mercurial to clone the repository or retrieve everything in an archive file
  • 6.
    Prerequisites for handson labsJava 1.6 JDK installationMaven 2 That’s it…Maven will take care of resolving all the other dependencies
  • 7.
    Maven 2Maven2 installationrequiredWe’re using version 2.2.1This is not a Maven presentationWe use it because it’s quite handy and does a great job of resolving dependenciesMaven commands will be presented when needed
  • 8.
  • 9.
    Sample web applicationStartingthe web appmvn jetty:run-explodedRunning testsmvn testsRunning cuke4dukemvn cuke4duke:cucumber
  • 10.
    Design principlesSingle responsibilityper class (high cohesion)Loose coupling of collaborators (low coupling)Injection of dependencies
  • 11.
    Why Groovy?Groovy worksseamlessly with JavaIt’s all just bytecode in the endGroovy offers a relaxed Java syntaxInteresting tools included in Groovy GSQLXmlSlurper, XmlParser, BuildersGPathConvenient collectionsPrivate method testing
  • 12.
    GroovyTestCaseIncluded in GroovydistributionExtends junit.framework.TestCaseProvides a number of helper methods for assertions Does not require test* methods to be void return typeNo need to declared throws checked exceptions in testsGroovy converts checked exceptions to unchecked exceptions
  • 13.
    Convenience assert methodsassertArrayEquals(Object[]expected, Object[] actual)assertContains(char expected, char[] actualArray)assertContains(int expected, int[] actualArray)assertInspect(Object value, String expected)assertLength(int length, Object[] array)assertScript(String script)assertToString(Object value, String expected)
  • 14.
    shouldFail() closuresshouldFail(Closure closure)Assertssupplied closure fails when evaluatedshouldFail(Class desiredThrownType, Closure closure)Asserts supplied closure fails when evaluated and particular exception type is thrownshouldFailWithCause(Class desiredCauseType, Closure closure)Will check for a checked exception as the root cause (checked exceptions are wrapped in Groovy)
  • 15.
    Mocking Java classeswith GroovyMap coercionGroovy’s mock libraryGMock libraryJava mocking frameworks
  • 16.
    Map coercionAdd namedclosures to the mapOnly one closure can be mapped to a “method name”Cannot overload methodsCoerce to desire type using the as operator
  • 17.
  • 18.
    Private Method CallingGroovycan call private methodsBroken encapsulation? Better reflection abstractions?Java can invoke private methods, it’s just more painfulIs testing private methods Good or a Smell?
  • 19.
  • 20.
    Groovy mocking libraryGroovy'sbuilt-in mock support does not allow us to test Java classesRelies on hooking into Groovy's object lifecycle mechanismsJava can not make call to Groovy Mock or StubUse Java mocking frameworks insteadCan cheat by putting Groovy Mock in a coerced map but why??
  • 21.
    GMockGroovy-based mock objectsframeworkEasy syntax and usageWorks when called by Java classes
  • 22.
    GMockCreate MockAddressService service= mock(AddressService)Create Expectationservice.fetch(“id”).returns(new Address()).once()Easy Mathcingservice.save(match{it.personId == “id”}).returns(“id”).once()
  • 23.
  • 24.
    Java Mocking FrameworksJavaMocking frameworks can be used with GroovySome have minor syntax issues or needed work arounds (JMock)Great to use if you already have one you are using and don’t want to switch
  • 25.
    GSQLEasy to createconnectionssql= Sql.newInstance("jdbc:hsqldb:hsql://localhost/", "sa", "", "org.hsqldb.jdbcDriver")Simple to work with row setssql.rows(“select * from address”).each {println “id: ${it.id}”}No try catch blocks
  • 26.
  • 27.
    Acceptance Test-DrivenStory testsmanifest themselves as executable testsDrives the development of complete featuresFrameworks are availableFit, FitLibrary, FitNessehttp://fit.c2.com/Robot Framework http://code.google.com/p/robotframework/Cucumber http://cukes.info/Others
  • 28.
    CucumberTool for executingplain-text functional descriptions as automated testsSupports BDDCucumber tests are typically written before anything elseverified by business analysts, domain experts, non-technical stakeholders The production code is then written to make the Cucumber tests passOutside-in development
  • 29.
    Cucumber (via cuke4duke)Cucumberfor the JVMOutside-in testingFacilitates automation of acceptance/story testsFeatures and scenarios use normal languageStep definitions can be written in Groovy, as we’ll seeUses JRuby to run the core Cucumber frameworkhttp://wiki.github.com/aslakhellesoy/cuke4duke/
  • 30.
    Cucumber featuresPurposesDocumentation ofthe systemAutomated, executable acceptance testsWhat code should I write next? Written in GherkinBusiness readable DSLDescribe software behavior without detailing implementationGrammar exists in different spoken languages (37 currently)Feature source files have .feature extension
  • 31.
    Given-When-ThenScenarios consist ofstepsGiven: Put the system in a known state before the user starts interacting with the system; pre-conditionsWhen: Describe the key action a user performs in this scenarioThen: Observe outcomes; observations should relate to business value of the featureUse And and But to keep features fluent
  • 32.
    Cucumber step definitionsWrittenin Groovy for our examplesCan be written in many different programming languagesAnalogous to method or function definitionStart with adjective/adverbRegular expression which will match some text from a feature(s)Take 0 or more argumentsArguments bound to regular expression groupsMulti-line step arguments
  • 33.
    HooksBeforeExecutes before thefirst step of each scenarioAfterExecutes after the last step of each scenarioExecute regardless if there are failing, undefined, pending or skipped stepsAfterStepExecutes after each step in a scenario
  • 34.
    HooksFound in Groovyfiles in the support directoryOur example uses one: env.groovyHooks allow us to run blocks of code at various points in the Cucumber test cycleNo association between where the hook is defined and which scenario/step it is run forAll defined hooks (one or more) are run whenever the relevant event occurs
  • 35.
    Tagged hooksNeed toexecute a certain hook for only certain scenariosAchieved by associating a Before, After or AfterStep hook with one or more tagsSee the env.groovy fileIt uses a Before hook with a @database tag to load the database via DBUnit
  • 36.
    Tagging scenariosAllows youto group scenarios for inclusion or exclusion in a Cucumber run@wip is provided out of the boxUsing tags in cuke4duke and Maven…mvn cuke4duke:cucumber –DcukeArgs=“--tags @wip”mvn cuke4duke:cucumber -DcukeArgs=“--tags ~@wip”Inside of the Maven POM: <cucumberArg>${cukeArgs}</cucumberArg>
  • 37.
    Running cuke4dukeThe cuke4dukeMaven pluginmvn cuke4duke:cucumberFirst time: use –Dcucumber.installGems=trueAdd –o option to work offlineFeatures and step definitions are discovered by the pluginFeatures belong in features directoryStep definitions found in the step_definitions directory
  • 38.
    cuke4duke acceptance testsStepdefinitions will be written in GroovyOther JVM languages are allowedUse cuke4duke.GroovyDslUse WebDriver: http://code.google.com/p/seleniumTest web UIUse DbUnit: http://www.dbunit.org/Bulk load the database with known fixture data
  • 39.
  • 40.
  • 41.
    Workshop activitiesNow it’syour turn!Try your hand at unit testing with GroovyRefactor the existing web appIntroduce DAO for database functionalityAdd services to orchestrate business logicWrite some Cucumber features and build out or reuse the Groovy step definitionsTry to add new features and practice outside-in developmentIs ATDD beneficial? Why or why not?
  • 42.
  • 43.

Editor's Notes

  • #19 NEW
  • #29 Behaviour-driven development is an “outside-in” methodology. It starts at the outside by identifying business outcomes, and then drills down into the feature set that will achieve those outcomes. Each feature is captured as a “story”, which defines the scope of the feature along with its acceptance criteria. This article introduces the BDD approach to defining and identifying stories and their acceptance criteria.