Test Driven In Groovy


Published on

Using Groovy for unit and acceptance testing. Includes material on GMock and cuke4duke.

  • Be the first to comment

No Downloads
Total views
On SlideShare
From Embeds
Number of Embeds
Embeds 0
No embeds

No notes for slide
  • NEW
  • 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.
  • Test Driven In Groovy

    1. 1. Test-Driven in Groovy<br />Joseph Muraski<br />Christopher Bartling<br />
    2. 2. Joseph Muraski<br />Independent Consultant in the Twin Cities<br />Develop enterprise applications using Java, .Net, Groovy, Grails…<br />Email: joe.muraski@mantacs.com<br />Twitter: jmuraski<br />Blog: joemuraski.blogspot.com<br />
    3. 3. Christopher Bartling<br />Independent consultant, based in the Twin Cities<br />Teach, mentor and coach for DevJam<br />Experiences include building enterprise applications with Java, Groovy, Grails, .NET, and Adobe Flex<br />Email: chris.bartling@gmail.com<br />Twitter: cbartling<br />Blog: bartling.blogspot.com<br />
    4. 4. Goals of the workshop<br />Introduce features in Groovy that will help your Java testing efforts<br />Introduce Cucumber and cuke4duke as new tools in your testing arsenal <br />Demonstrate unit, integration, and acceptance testing with Groovy and Cucumber (via cuke4duke) via an example Java web application<br />Get hands on with these technologies <br />
    5. 5. Summary<br />Design principles<br />Testing facilities built into Groovy<br />Acceptance/BDD testing with Groovy <br />Cucumber and cuke4duke<br />Presentation and code available <br />http://bitbucket.org/joe.muraski/grails_tdd_workshop/<br />Instructions on how to use Mercurial to clone the repository or retrieve everything in an archive file<br />
    6. 6. Prerequisites for hands on labs<br />Java 1.6 JDK installation<br />Maven 2 <br />That’s it…Maven will take care of resolving all the other dependencies<br />
    7. 7. Maven 2<br />Maven2 installation required<br />We’re using version 2.2.1<br />This is not a Maven presentation<br />We use it because it’s quite handy and does a great job of resolving dependencies<br />Maven commands will be presented when needed<br />
    8. 8. Maven plugins used<br />org.codehaus.gmaven:gmaven-plugin:1.2<br />org.mortbay.jetty:maven-jetty-plugin<br />cuke4duke:cuke4duke-maven-plugin:0.2.4<br />org.apache.maven.plugins:maven-surefire-plugin<br />
    9. 9. Sample web application<br />Starting the web app<br />mvn jetty:run-exploded<br />Running tests<br />mvn tests<br />Running cuke4duke<br />mvn cuke4duke:cucumber<br />
    10. 10. Design principles<br />Single responsibility per class (high cohesion)<br />Loose coupling of collaborators (low coupling)<br />Injection of dependencies<br />
    11. 11. Why Groovy?<br />Groovy works seamlessly with Java<br />It’s all just bytecode in the end<br />Groovy offers a relaxed Java syntax<br />Interesting tools included in Groovy <br />GSQL<br />XmlSlurper, XmlParser, Builders<br />GPath<br />Convenient collections<br />Private method testing<br />
    12. 12. GroovyTestCase<br />Included in Groovy distribution<br />Extends junit.framework.TestCase<br />Provides a number of helper methods for assertions <br />Does not require test* methods to be void return type<br />No need to declared throws checked exceptions in tests<br />Groovy converts checked exceptions to unchecked exceptions<br />
    13. 13. Convenience assert methods<br />assertArrayEquals(Object[] expected, Object[] actual)<br />assertContains(char expected, char[] actualArray)<br />assertContains(int expected, int[] actualArray)<br />assertInspect(Object value, String expected)<br />assertLength(int length, Object[] array)<br />assertScript(String script)<br />assertToString(Object value, String expected)<br />
    14. 14. shouldFail() closures<br />shouldFail(Closure closure)<br />Asserts supplied closure fails when evaluated<br />shouldFail(Class desiredThrownType, Closure closure)<br />Asserts supplied closure fails when evaluated and particular exception type is thrown<br />shouldFailWithCause(Class desiredCauseType, Closure closure)<br />Will check for a checked exception as the root cause (checked exceptions are wrapped in Groovy)<br />
    15. 15. Mocking Java classes with Groovy<br />Map coercion<br />Groovy’s mock library<br />GMock library<br />Java mocking frameworks<br />
    16. 16. Map coercion<br />Add named closures to the map<br />Only one closure can be mapped to a “method name”<br />Cannot overload methods<br />Coerce to desire type using the as operator<br />
    17. 17. Map coercion example<br />
    18. 18. Private Method Calling<br />Groovy can call private methods<br />Broken encapsulation? <br />Better reflection abstractions?<br />Java can invoke private methods, it’s just more painful<br />Is testing private methods Good or a Smell?<br />
    19. 19. Private method testing example<br />
    20. 20. Groovy mocking library<br />Groovy's built-in mock support does not allow us to test Java classes<br />Relies on hooking into Groovy's object lifecycle mechanisms<br />Java can not make call to Groovy Mock or Stub<br />Use Java mocking frameworks instead<br />Can cheat by putting Groovy Mock in a coerced map but why??<br />
    21. 21. GMock<br />Groovy-based mock objects framework<br />Easy syntax and usage<br />Works when called by Java classes<br />
    22. 22. GMock<br />Create Mock<br />AddressService service = mock(AddressService)<br />Create Expectation<br />service.fetch(“id”).returns(new Address()).once()<br />Easy Mathcing<br />service.save(match{it.personId == “id”}).returns(“id”).once()<br />
    23. 23. GMock example<br />
    24. 24. Java Mocking Frameworks<br />Java Mocking frameworks can be used with Groovy<br />Some have minor syntax issues or needed work arounds (JMock)<br />Great to use if you already have one you are using and don’t want to switch<br />
    25. 25. GSQL<br />Easy to create connections<br />sql= Sql.newInstance("jdbc:hsqldb:hsql://localhost/", "sa", "", "org.hsqldb.jdbcDriver")<br />Simple to work with row sets<br />sql.rows(“select * from address”).each {println “id: ${it.id}”}<br />No try catch blocks<br />
    26. 26. GSQL example<br />
    27. 27. Acceptance Test-Driven<br />Story tests manifest themselves as executable tests<br />Drives the development of complete features<br />Frameworks are available<br />Fit, FitLibrary, FitNesse<br />http://fit.c2.com/<br />Robot Framework <br />http://code.google.com/p/robotframework/<br />Cucumber <br />http://cukes.info/<br />Others<br />
    28. 28. Cucumber<br />Tool for executing plain-text functional descriptions as automated tests<br />Supports BDD<br />Cucumber tests are typically written before anything else<br />verified by business analysts, domain experts, non-technical stakeholders <br />The production code is then written to make the Cucumber tests pass<br />Outside-in development<br />
    29. 29. Cucumber (via cuke4duke)<br />Cucumber for the JVM<br />Outside-in testing<br />Facilitates automation of acceptance/story tests<br />Features and scenarios use normal language<br />Step definitions can be written in Groovy, as we’ll see<br />Uses JRuby to run the core Cucumber framework<br />http://wiki.github.com/aslakhellesoy/cuke4duke/<br />
    30. 30. Cucumber features<br />Purposes<br />Documentation of the system<br />Automated, executable acceptance tests<br />What code should I write next? <br />Written in Gherkin<br />Business readable DSL<br />Describe software behavior without detailing implementation<br />Grammar exists in different spoken languages (37 currently)<br />Feature source files have .feature extension<br />
    31. 31. Given-When-Then<br />Scenarios consist of steps<br />Given: Put the system in a known state before the user starts interacting with the system; pre-conditions<br />When: Describe the key action a user performs in this scenario<br />Then: Observe outcomes; observations should relate to business value of the feature<br />Use And and But to keep features fluent<br />
    32. 32. Cucumber step definitions<br />Written in Groovy for our examples<br />Can be written in many different programming languages<br />Analogous to method or function definition<br />Start with adjective/adverb<br />Regular expression which will match some text from a feature(s)<br />Take 0 or more arguments<br />Arguments bound to regular expression groups<br />Multi-line step arguments<br />
    33. 33. Hooks<br />Before<br />Executes before the first step of each scenario<br />After<br />Executes after the last step of each scenario<br />Execute regardless if there are failing, undefined, pending or skipped steps<br />AfterStep<br />Executes after each step in a scenario<br />
    34. 34. Hooks<br />Found in Groovy files in the support directory<br />Our example uses one: env.groovy<br />Hooks allow us to run blocks of code at various points in the Cucumber test cycle<br />No association between where the hook is defined and which scenario/step it is run for<br />All defined hooks (one or more) are run whenever the relevant event occurs <br />
    35. 35. Tagged hooks<br />Need to execute a certain hook for only certain scenarios<br />Achieved by associating a Before, After or AfterStep hook with one or more tags<br />See the env.groovy file<br />It uses a Before hook with a @database tag to load the database via DBUnit <br />
    36. 36. Tagging scenarios<br />Allows you to group scenarios for inclusion or exclusion in a Cucumber run<br />@wip is provided out of the box<br />Using tags in cuke4duke and Maven…<br />mvn cuke4duke:cucumber –DcukeArgs=“--tags @wip”<br />mvn cuke4duke:cucumber -DcukeArgs=“--tags ~@wip”<br />Inside of the Maven POM: <cucumberArg>${cukeArgs}</cucumberArg><br />
    37. 37. Running cuke4duke<br />The cuke4duke Maven plugin<br />mvn cuke4duke:cucumber<br />First time: use –Dcucumber.installGems=true<br />Add –o option to work offline<br />Features and step definitions are discovered by the plugin<br />Features belong in features directory<br />Step definitions found in the step_definitions directory<br />
    38. 38. cuke4duke acceptance tests<br />Step definitions will be written in Groovy<br />Other JVM languages are allowed<br />Use cuke4duke.GroovyDsl<br />Use WebDriver: http://code.google.com/p/selenium<br />Test web UI<br />Use DbUnit: http://www.dbunit.org/<br />Bulk load the database with known fixture data <br />
    39. 39. Acceptance testing configuration<br />
    40. 40. Cucumber examples<br />
    41. 41. Workshop activities<br />Now it’s your turn!<br />Try your hand at unit testing with Groovy<br />Refactor the existing web app<br />Introduce DAO for database functionality<br />Add services to orchestrate business logic<br />Write some Cucumber features and build out or reuse the Groovy step definitions<br />Try to add new features and practice outside-in development<br />Is ATDD beneficial? Why or why not?<br />
    42. 42. Interesting resources<br />http://cukes.info/<br />http://blog.dannorth.net/whats-in-a-story/<br />http://blog.dannorth.net/introducing-bdd/<br />http://www.ibm.com/developerworks/java/library/j-pg11094/<br />http://wiki.github.com/aslakhellesoy/cucumber/<br />
    43. 43. Discussion<br />