test-driven in groovy
DESCRIPTION
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: [email protected] Twitter: jmuraski Blog: joemuraski.blogspot.com. - PowerPoint PPT PresentationTRANSCRIPT
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: [email protected] Twitter: jmuraski Blog: joemuraski.blogspot.com
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: [email protected] Twitter: cbartling Blog: bartling.blogspot.com
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
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
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
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
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
Sample web application
Starting the web app mvn jetty:run-exploded
Running tests mvn tests
Running cuke4duke mvn cuke4duke:cucumber
Design principles
Single responsibility per class (high cohesion) Loose coupling of collaborators (low coupling) Injection of dependencies
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
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
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)
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)
Mocking Java classes with Groovy
Map coercion Groovy’s mock library GMock library Java mocking frameworks
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
Map coercion example
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?
Private method testing example
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??
GMock
Groovy-based mock objects framework Easy syntax and usage Works when called by Java classes
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()
GMock example
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
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
GSQL example
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
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
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/
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
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
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
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
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
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
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>
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
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
Acceptance testing configuration
Cucumber examples
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?
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-pg1
1094/ http://wiki.github.com/aslakhellesoy/cucumber/
Discussion