1 / 43

Test-Driven in Groovy

Test-Driven in Groovy. Joseph Muraski Christopher Bartling. Joseph Muraski. Independent Consultant in the Twin Cities Develop enterprise applications using Java, .Net , Groovy, Grails… Email: joe.muraski@mantacs.com Twitter: jmuraski Blog: joemuraski.blogspot.com.

yael
Download Presentation

Test-Driven in Groovy

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. Test-Driven in Groovy Joseph Muraski Christopher Bartling

  2. Joseph Muraski • Independent Consultant in the Twin Cities • Develop enterprise applications using Java, .Net, Groovy, Grails… • Email: joe.muraski@mantacs.com • Twitter: jmuraski • Blog: joemuraski.blogspot.com

  3. Christopher Bartling • Independent consultant, based in the Twin Cities • Teach, mentor and coach for DevJam • Experiences include building enterprise applications with Java, Groovy, Grails, .NET, and Adobe Flex • Email: chris.bartling@gmail.com • Twitter: cbartling • Blog: bartling.blogspot.com

  4. Goals of the workshop • Introduce features in Groovy that will help your Java testing efforts • Introduce 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 application • Get hands on with these technologies

  5. Summary • Design principles • Testing facilities built into Groovy • Acceptance/BDD testing with Groovy • Cucumber and cuke4duke • Presentation 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 hands on labs • Java 1.6 JDK installation • Maven 2 • That’s it…Maven will take care of resolving all the other dependencies

  7. Maven 2 • Maven2 installation required • We’re using version 2.2.1 • This is not a Maven presentation • We use it because it’s quite handy and does a great job of resolving dependencies • Maven commands will be presented when needed

  8. Maven plugins used • org.codehaus.gmaven:gmaven-plugin:1.2 • org.mortbay.jetty:maven-jetty-plugin • cuke4duke:cuke4duke-maven-plugin:0.2.4 • org.apache.maven.plugins:maven-surefire-plugin

  9. Sample web application • Starting the web app • mvn jetty:run-exploded • Running tests • mvn tests • Running cuke4duke • mvn cuke4duke:cucumber

  10. Design principles • Single responsibility per class (high cohesion) • Loose coupling of collaborators (low coupling) • Injection of dependencies

  11. Why Groovy? • Groovy works seamlessly with Java • It’s all just bytecode in the end • Groovy offers a relaxed Java syntax • Interesting tools included in Groovy • GSQL • XmlSlurper, XmlParser, Builders • GPath • Convenient collections • Private method testing

  12. GroovyTestCase • Included in Groovy distribution • Extends junit.framework.TestCase • Provides a number of helper methods for assertions • Does not require test* methods to be void return type • No need to declared throws checked exceptions in tests • Groovy converts checked exceptions to unchecked exceptions

  13. Convenience assert methods • assertArrayEquals(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() closures • shouldFail(Closure closure) • Asserts supplied closure fails when evaluated • shouldFail(Class desiredThrownType, Closure closure) • Asserts supplied closure fails when evaluated and particular exception type is thrown • shouldFailWithCause(Class desiredCauseType, Closure closure) • Will check for a checked exception as the root cause (checked exceptions are wrapped in Groovy)

  15. Mocking Java classes with Groovy • Map coercion • Groovy’s mock library • GMock library • Java mocking frameworks

  16. Map coercion • Add named closures to the map • Only one closure can be mapped to a “method name” • Cannot overload methods • Coerce to desire type using the as operator

  17. Map coercion example

  18. Private Method Calling • Groovy can call private methods • Broken encapsulation? • Better reflection abstractions? • Java can invoke private methods, it’s just more painful • Is testing private methods Good or a Smell?

  19. Private method testing example

  20. Groovy mocking library • Groovy's built-in mock support does not allow us to test Java classes • Relies on hooking into Groovy's object lifecycle mechanisms • Java can not make call to Groovy Mock or Stub • Use Java mocking frameworks instead • Can cheat by putting Groovy Mock in a coerced map but why??

  21. GMock • Groovy-based mock objects framework • Easy syntax and usage • Works when called by Java classes

  22. GMock • Create Mock • AddressService service = mock(AddressService) • Create Expectation • service.fetch(“id”).returns(new Address()).once() • Easy Mathcing • service.save(match{it.personId == “id”}).returns(“id”).once()

  23. GMock example

  24. Java Mocking Frameworks • Java Mocking frameworks can be used with Groovy • Some 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. GSQL • Easy to create connections • con = Sql.newInstance("jdbc:hsqldb:hsql://localhost/", "sa", "", "org.hsqldb.jdbcDriver") • Simple to work with row sets • con.rows(“select * from address”).each {println “id: ${it.id}”} • No try catch blocks

  26. GSQL example

  27. Acceptance Test-Driven • Story tests manifest themselves as executable tests • Drives the development of complete features • Frameworks are available • Fit, FitLibrary, FitNesse • http://fit.c2.com/ • Robot Framework • http://code.google.com/p/robotframework/ • Cucumber • http://cukes.info/ • Others

  28. Cucumber • Tool for executing plain-text functional descriptions as automated tests • Supports BDD • Cucumber tests are typically written before anything else • verified by business analysts, domain experts, non-technical stakeholders • The production code is then written to make the Cucumber tests pass • Outside-in development

  29. Cucumber (via cuke4duke) • Cucumber for the JVM • Outside-in testing • Facilitates automation of acceptance/story tests • Features and scenarios use normal language • Step definitions can be written in Groovy, as we’ll see • Uses JRuby to run the core Cucumber framework • http://wiki.github.com/aslakhellesoy/cuke4duke/

  30. Cucumber features • Purposes • Documentation of the system • Automated, executable acceptance tests • What code should I write next? • Written in Gherkin • Business readable DSL • Describe software behavior without detailing implementation • Grammar exists in different spoken languages (37 currently) • Feature source files have .feature extension

  31. Given-When-Then • Scenarios consist of steps • Given: Put the system in a known state before the user starts interacting with the system; pre-conditions • When: Describe the key action a user performs in this scenario • Then: Observe outcomes; observations should relate to business value of the feature • Use And and But to keep features fluent

  32. Cucumber step definitions • Written in Groovy for our examples • Can be written in many different programming languages • Analogous to method or function definition • Start with adjective/adverb • Regular expression which will match some text from a feature(s) • Take 0 or more arguments • Arguments bound to regular expression groups • Multi-line step arguments

  33. Hooks • Before • Executes before the first step of each scenario • After • Executes after the last step of each scenario • Execute regardless if there are failing, undefined, pending or skipped steps • AfterStep • Executes after each step in a scenario

  34. Hooks • Found in Groovy files in the support directory • Our example uses one: env.groovy • Hooks allow us to run blocks of code at various points in the Cucumber test cycle • No association between where the hook is defined and which scenario/step it is run for • All defined hooks (one or more) are run whenever the relevant event occurs

  35. Tagged hooks • Need to execute a certain hook for only certain scenarios • Achieved by associating a Before, After or AfterStep hook with one or more tags • See the env.groovy file • It uses a Before hook with a @database tag to load the database via DBUnit

  36. Tagging scenarios • Allows you to group scenarios for inclusion or exclusion in a Cucumber run • @wip is provided out of the box • Using 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 cuke4duke • The cuke4duke Maven plugin • mvn cuke4duke:cucumber • First time: use –Dcucumber.installGems=true • Add –o option to work offline • Features and step definitions are discovered by the plugin • Features belong in features directory • Step definitions found in the step_definitions directory

  38. cuke4duke acceptance tests • Step definitions will be written in Groovy • Other JVM languages are allowed • Use cuke4duke.GroovyDsl • Use WebDriver: http://code.google.com/p/selenium • Test web UI • Use DbUnit: http://www.dbunit.org/ • Bulk load the database with known fixture data

  39. Acceptance testing configuration

  40. Cucumber examples

  41. Workshop activities • Now it’s your turn! • Try your hand at unit testing with Groovy • Refactor the existing web app • Introduce DAO for database functionality • Add services to orchestrate business logic • Write some Cucumber features and build out or reuse the Groovy step definitions • Try to add new features and practice outside-in development • Is ATDD beneficial? Why or why not?

  42. Interesting resources • http://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/

  43. Discussion

More Related