Grails 1.1 Testing - Unit, Integration & Functional
Upcoming SlideShare
Loading in...5
×
 

Grails 1.1 Testing - Unit, Integration & Functional

on

  • 8,461 views

A walkthrough of the benefits, drawbacks, new features, important "gotchas" and some code samples using the testing features available in Grails 1.1....

A walkthrough of the benefits, drawbacks, new features, important "gotchas" and some code samples using the testing features available in Grails 1.1.

We'll be covering:

- unit testing (specifically GrailsUnitTestCase and it's extensions)
- integration testing
- functional testing (using WebTest)

Statistics

Views

Total Views
8,461
Views on SlideShare
8,374
Embed Views
87

Actions

Likes
8
Downloads
162
Comments
1

5 Embeds 87

http://www.slideshare.net 70
http://www.techgig.com 14
http://webcache.googleusercontent.com 1
http://www.m.techgig.com 1
http://www.apurva.com 1

Accessibility

Categories

Upload Details

Uploaded via as Microsoft PowerPoint

Usage Rights

© All Rights Reserved

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel

11 of 1

  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Processing…
  • Feel free to comment on this over on my related blog post: http://www.2paths.com/2009/07/20/grails-11-testing-unit-integration-functional

    Thanks!
    Dave
    Are you sure you want to
    Your message goes here
    Processing…
Post Comment
Edit your comment

    Grails 1.1 Testing - Unit, Integration & Functional Grails 1.1 Testing - Unit, Integration & Functional Presentation Transcript

    • Grails 1.1 Testing
      Tech Talk @ 2Paths
      July 17, 2009
      By Dave Koo
      ©2009 - 2Paths Solutions Ltd. (www.2paths.com)
      7/17/09
    • Agenda
      Unit Testing
      Integration Testing
      Functional Testing
      Putting It All Together
      ©2009 - 2Paths Solutions Ltd. (www.2paths.com)
      7/17/09
    • Unit Testing - Overview
      unit tests enable testing small bits of code in isolation
      Grails does NOT inject any surrounding infrastructure (ie. no dynamic GORM methods, database, Spring resources, bootstrap, ServletContext, etc)
      ©2009 - 2Paths Solutions Ltd. (www.2paths.com)
      7/17/09
    • Unit Testing - Benefits
      find problems sooner -> you can test your code before all it's dependencies are created/available
      enables safer refactoring (of individual classes)
      faster to run than integration & functional tests
      there isn't a big speed gap early in the project (PLAID: unit ~ 10s, integration ~ 30)
      but it grows as the system gets bigger
      makes TDD less painful -> breaks problem into smaller pieces
      provides form of API documentation & spec
      ©2009 - 2Paths Solutions Ltd. (www.2paths.com)
      7/17/09
    • Unit Testing - Drawbacks
      more code to maintain & debug -> often as buggy as code under test (if written by same person :)
      sometimes you have to mock a LOT of stuff before you can write your little test
      doesn't catch bugs at the integration or UI layers -> can create false sense of security
      ©2009 - 2Paths Solutions Ltd. (www.2paths.com)
      7/17/09
    • Unit Testing – GrailsUnitTestCaseOverview
      extends GroovyTestCase to add Grails-specific mocking and make testing more convenient for Grails users
      mocking is test-specific and doesn't leak from one test to another
      avoids having to do a lot of MetaClass hacking (and forgetting to teardown your metaclass hacking :)
      ©2009 - 2Paths Solutions Ltd. (www.2paths.com)
      7/17/09
    • Unit Testing – GrailsUnitTestCasemethods
      mockFor(class, loose = false)
      mockDomain(class, testInstances[ ])
      mockForConstraintsTests(class, testInstances[ ])
      mockLogging(class, enableDebug = false)
      Code samples: http://grails.org/doc/1.1.1/guide/9.%20Testing.html#9.1%20Unit%20Testing
      ©2009 - 2Paths Solutions Ltd. (www.2paths.com)
      7/17/09
    • Unit Testing – GrailsUnitTestCasemockFor(class, loose = false)
      generic mocker for mocking methods of any class
      returns a control object (not the actual mock)
      loose - false == strict mocking (sequence of expected method calls matters), true == loose (sequence doesn't matter)
      methods - you can mock instance or static methods
      demands - your expectations of the mock
      range - number of times a method is expected to be called (default === 1)
      closure - mock implementation of the method
      strictControl.createMock() - returns an actual mock object
      strictControl.verify() - verifies that all demands were actually met
      ©2009 - 2Paths Solutions Ltd. (www.2paths.com)
      7/17/09
    • Unit Testing – GrailsUnitTestCasemockDomain(class, testInstances[ ])
      mocks all methods (instance, static & dynamic) on a domain class
      testInstances- a list of domain class instances which replaces and acts as the "database”
      you can call save(), findBy*(), validate(), etc on an instance of a mocked domain class
      inheritance can be tricky!
      assume you have ParentClass, ChildA, ChildB
      if you mock ParentClass and pass a collection of instances containing ChildA and/or ChildB objects to the MockDomain() method, you must ensure that you have already mocked each type of ChildX class in the instance collection. This is needed even if you NEVER call a dynamic method on any child class (such as ChildClass.list()).
      always mock a child class BEFORE mocking its parent, otherwise you may get "Method Not Found" exceptions when calling dynamic methods on the child
      new addition to Grails
      still some bugs / missing features
      check Grails' JIRA & mailing lists if experiencing wierdbehaviour
      ©2009 - 2Paths Solutions Ltd. (www.2paths.com)
      7/17/09
    • Unit Testing – GrailsUnitTestCaseother methods…
      mockForConstraintsTests(class, testInstances[ ])
      Stripped-down version of mockDomain that allows for assertions to validate domain class constraints
      Takes the pain out of testing domain class constraints
      mockLogging(class, enableDebug = false)
      Adds a mock "log" property to a class. Any messages passed to the mock logger are echoed to the console.
      ©2009 - 2Paths Solutions Ltd. (www.2paths.com)
      7/17/09
    • Unit Testing – ControllerUnitTestCase
      extends GrailsUnitTestCase to add mocks for:
      all dynamic properties & methods Grails injects into controllers (render, redirect, model, etc)
      all HTTP objects available to controllers (request, response, session, params, flash, etc)
      command object (if needed)
      provides an implicit "controller" property which contains all the above mocks (no need to def the controller yourself in your test class)
      don't forget to mock your Domain objects as needed if the controller action you call expects a database
      ©2009 - 2Paths Solutions Ltd. (www.2paths.com)
      7/17/09
    • Unit Testing – Other Unit Tests
      TagLibUnitTestCase
      extends GrailsUnitTestCase to add mocks for dynamic properties & methods a TagLibexpects
      dbUnit
      extends jUnit to allow you to test that your DB is in the expected state
      prevents subsequent tests from failing due to a previous test leaving the database "dirty"
      ©2009 - 2Paths Solutions Ltd. (www.2paths.com)
      7/17/09
    • Integration Testing - Overview
      used to test that an entire module or sub-system consisting of multiple classes is working correctly (in isolation)
      one level below a functional test as integration tests do not test the entire stack
      Grails injects all the surrounding infrastructure such as data sources & Spring beans
      pretty straightforward to implement since there's generally no mocking involved
      where to use integration tests??? we'll come back to this in a few mins :)
      ©2009 - 2Paths Solutions Ltd. (www.2paths.com)
      7/17/09
    • Integration Testing - Benefits
      tests the real interactions between individual pieces
      finds more complex bugs that unit tests can't find
      faster to run than functional tests (usually)
      makes large-scale refactoring safer
      find bugs sooner -> doesn't require other system modules to be built
      ©2009 - 2Paths Solutions Ltd. (www.2paths.com)
      7/17/09
    • Integration Testing - Drawbacks
      perhaps overused by lazy testers who don't feel like mocking :)
      requires more code to be written than unit tests
      doesn't find system-level or inter-module bugs
      value is debatable if you have good functional tests & good unit tests.
      ©2009 - 2Paths Solutions Ltd. (www.2paths.com)
      7/17/09
    • Functional Testing - Overview
      used to test functionality from an end user's perspective across all layers of the system
      ©2009 - 2Paths Solutions Ltd. (www.2paths.com)
      7/17/09
    • Functional Testing - Benefits
      finds complex system-level and inter-module bugs
      finds UI bugs
      can be written by non-techies (depends on tool used)
      provides "done when" acceptance criteria for the customer
      provides a form of user documentation
      makes large-scale refactoring safer
      ©2009 - 2Paths Solutions Ltd. (www.2paths.com)
      7/17/09
    • Functional Testing - Drawbacks
      very slow to execute HTTP level tests
      often more cumbersome to write than other types of tests
      often brittle and can require a lot of maintenance (especially if tied to UI)
      Usually hard to write until UI is available (and stable)
      ©2009 - 2Paths Solutions Ltd. (www.2paths.com)
      7/17/09
    • Functional Testing - Tools
      CanooWebTest& Grails Functional Testing
      Both wrap HtmlUnit which provides a Java API that mocks a web browser
      CanooWebTest
      wrapper for WebTest's XML syntax
      and therefore constrained by the underlying XML syntax
      Grails Functional Testing
      pure-groovy solution
      more flexible, but newer & therefore fewer features than WebTest
      ©2009 - 2Paths Solutions Ltd. (www.2paths.com)
      7/17/09
    • Functional Testing - WebTest
      test organization & re-use
      grouping steps with ant.group
      calling methods from other tests
      Groovy step
      notation uses 3 double-quotes as Groovy code delimeter (“””)
      accessing HtmlUnit for fine-grained test control
      parameter passing between app context & WebTest context
      AJAX testing w/ sleep()
      ©2009 - 2Paths Solutions Ltd. (www.2paths.com)
      7/17/09
    • Functional Testing – WebTestgrouping steps with ant.group
      if your test has dozens of steps, it gets hard to read the report
      grouping steps with ant.group rolls them up to 1 line in the test report, which can be easily expanded/collapsed:
      ant.group(description: “verify bank account info”) { invoke “someController/someAction”verifyText “some text”verifyText “more text”}
      ©2009 - 2Paths Solutions Ltd. (www.2paths.com)
      7/17/09
    • Functional Testing – WebTestcalling methods from other tests
      Instead of copying & pasting the same methods from one test to another, you can call a method in another test by passing it your AntBuilder instance (ant) as a param. This ensures the test steps are executed using the calling test’s AntBuilder.
      ====== in CallingTestClass() ====def otherTestClass = new OtherTestClass()otherTestClass.someMethod(ant)====== in OtherTestClass() =====def someMethod(AntBuilderab) {ab.invoke“someController/someAction”ab.verifyText“some text”}
      ©2009 - 2Paths Solutions Ltd. (www.2paths.com)
      7/17/09
    • Functional Testing – WebTestGroovy step
      If you need to execute arbitrary Groovy code in your test, use WebTest’sgroovy step.
      Keep in mind that this groovy step won’t have access to any Groovy variables defined in your test (such as method params)…it only has access to the properties in the AntBuilder context.
      So you need to pass any needed params to the AntBuilder before entering your groovy step. Then you can retrieve them from the AntBuilder from within your step.
      The following example involves:
      Storing Groovy variables into AntBuilder properties
      Retrieving AntBuilder properties for use in the Groovy step
      Calling some HtmlUnit methods which aren’t available in WebTest for fine-grained test control
      Pausing the test for 2 seconds (very useful with AJAX tests to give the server time to respond
      ©2009 - 2Paths Solutions Ltd. (www.2paths.com)
      7/17/09
    • Functional Testing – WebTestGroovy step
      test method with Groovy step to test AJAX autocomplete form input:
      def setAJAXInputField(elementId, elementValue, AntBuilderab) {ab.storeProperty(property: 'elementId', value: elementId)
      ab.storeProperty(property: 'elementValue', value: elementValue)
      ab.groovy ""” def elementId = step.webtestProperties.elementId
      def elementValue = step.webtestProperties.elementValue def document = step.context.currentResponse.documentElement
      def element = document.getHtmlElementById(elementId)
      element.focus()
      element.type(elementValue)
      Thread.sleep(2000)“””
      }
      ©2009 - 2Paths Solutions Ltd. (www.2paths.com)
      7/17/09
    • Putting It All Together - Running tests
      test-app -> all tests
      test-app -unit -> all unit tests
      test-app -integration -> all integration tests
      test-app -unit AnnualReportAssignmentHandler-> 2 unit tests & all integration tests
      test-app AnnualReportAssignmentHandlerWorkflowManagerService-> 2 unit tests & 1 integration test
      run-webtest-> runs all tests using new server instance
      run-webtest -nostart-> runs all tests using existing Tomcat instance (much faster!!!)
      run-webtestClassNameTestName-> run TestName using existing Tomcat instance
      ©2009 - 2Paths Solutions Ltd. (www.2paths.com)
      7/17/09
    • Putting It All Together - Summary
      Unit testing - taglibs, controllers, services, domain classes (including contraints), other delegates & "helpers", even your data (dbUnit)
      Integration testing
      now that Grails 1.1 supports unit testing of controllers with ControllerUnitTestCase, that seems to be the preferred way of testing them (rather than using integration tests).
      This makes sense since controllers should not be doing the heavy lifting in a Grails app.
      The same holds true for TagLib testing with TagLibUnitTestCase.
      this leaves Services as the most valuable thing to cover with integration tests (but only after you’ve written unit tests for them )
      Functional testing - smoke tests, acceptance tests, regression tests
      Manual testing by humans - look & feel, anything not covered above
      ©2009 - 2Paths Solutions Ltd. (www.2paths.com)
      7/17/09