43
Test-Driven in Groovy Joseph Muraski Christopher Bartling

Test Driven In Groovy

Embed Size (px)

DESCRIPTION

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

Citation preview

Page 1: Test Driven In Groovy

Test-Driven in Groovy

Joseph Muraski

Christopher Bartling

Page 2: Test Driven In Groovy

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

Page 3: Test Driven In Groovy

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

Page 4: Test Driven In Groovy

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

Page 5: Test Driven In Groovy

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

Page 6: Test Driven In Groovy

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

Page 7: Test Driven In Groovy

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

Page 8: Test Driven In Groovy

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

Page 9: Test Driven In Groovy

Sample web application

Starting the web app mvn jetty:run-exploded

Running tests mvn tests

Running cuke4duke mvn cuke4duke:cucumber

Page 10: Test Driven In Groovy

Design principles

Single responsibility per class (high cohesion)

Loose coupling of collaborators (low coupling)

Injection of dependencies

Page 11: Test Driven In Groovy

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

Page 12: Test Driven In Groovy

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

Page 13: Test Driven In Groovy

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)

Page 14: Test Driven In Groovy

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)

Page 15: Test Driven In Groovy

Mocking Java classes with Groovy

Map coercion

Groovy’s mock library

GMock library

Java mocking frameworks

Page 16: Test Driven In Groovy

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

Page 17: Test Driven In Groovy

Map coercion example

Page 18: Test Driven In Groovy

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?

Page 19: Test Driven In Groovy

Private method testing example

Page 20: Test Driven In Groovy

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??

Page 21: Test Driven In Groovy

GMock

Groovy-based mock objects framework

Easy syntax and usage

Works when called by Java classes

Page 22: Test Driven In Groovy

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()

Page 23: Test Driven In Groovy

GMock example

Page 24: Test Driven In Groovy

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

Page 25: Test Driven In Groovy

GSQL

Easy to create connections sql= Sql.newInstance("jdbc:hsqldb:hsql://localhost/", "sa",

"", "org.hsqldb.jdbcDriver")

Simple to work with row sets sql.rows(“select * from address”).each {println “id: $

{it.id}”}

No try catch blocks

Page 26: Test Driven In Groovy

GSQL example

Page 27: Test Driven In Groovy

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

Page 28: Test Driven In Groovy

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

Page 29: Test Driven In Groovy

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/

Page 30: Test Driven In Groovy

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

Page 31: Test Driven In Groovy

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

Page 32: Test Driven In Groovy

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

Page 33: Test Driven In Groovy

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

Page 34: Test Driven In Groovy

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

Page 35: Test Driven In Groovy

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

Page 36: Test Driven In Groovy

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>

Page 37: Test Driven In Groovy

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

Page 38: Test Driven In Groovy

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

Page 39: Test Driven In Groovy

Acceptance testing configuration

Page 40: Test Driven In Groovy

Cucumber examples

Page 41: Test Driven In Groovy

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?

Page 42: Test Driven In Groovy

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/

Page 43: Test Driven In Groovy

Discussion