Skip to content

Instantly share code, notes, and snippets.

@jasongonzales23
Created August 2, 2012 20:27
Show Gist options
  • Save jasongonzales23/3240358 to your computer and use it in GitHub Desktop.
Save jasongonzales23/3240358 to your computer and use it in GitHub Desktop.
Testing GSP's with GroovyPagesTestCase

Overview

  • About Me
  • These are Integration Tests
  • How I Think About Tests
  • Anatomy of a Test
  • Assertions
  • Passing Models
  • Running the Test

About Me

I have not really been able to introduce myself to the team, so how about now?

  • I am a self-taught developer
  • I used to be a working musician, but still write and play music
  • I briefly taught English in public school
  • I love to cook
  • I love to eat

These are Simply Integration Tests

At the risk of insulting your intelligence...

  • Unit Tests test things like Controllers and Services in isolation.
  • Integration Tests will implement Controllers & Services to process a mock model that you pass to them.

How I Think About Tests

  • I tend to think of UI integration tests as testing behaviors users expect.
  • It helps to think of Integration Tests as being driven by user stories.
  • Each test should focus on a specific behavior

Example: As a Staff member, given that I attached a receipt in the Create Transaction modal, when still in the modal if I click on the 'View Receipt' icon it should open in a new window.

Now let's look at a test of that user story...

Anatomy of a Test

Here's what an integration test looks like:

import grails.test.GroovyPagesTestCase
class ReceiptAttacherTest extends GroovyPagesTestCase {
    def lineItemModelService
    def receiptService
    void testAttachReceiptFromCreateOrItemizeModal_AttachmentShouldOpenInNewWindow() {
        def file = new File("grails-app/views/receipt/_drawerReceipt.gsp")
        def result = applyTemplate(file.text, [
            attachReceiptOnCreate: true,
            item: [
                lineItemId: 1234,
                receipt: [
                    mediaType: 'image/jpeg',
                    originalUri: 'some/path',
                    receiptId: 5678,
                    name: 'jason'
                ]
            ]
      ])
      assertTrue(result.contains('target="_blank"'))
    }
}

How To Build the Test "Shell"

This is one way:

mvn grails:create-integration-test
  • It will prompt you for a name for the test.
  • Then it will create an 'expense' directory inside the 'integration' directory

But then you get a test that looks like this, and you have to change it:

package expense
import grails.test.*
class superImportantTests extends GroovyTestCase {
    protected void setUp() {
        super.setUp()
    }
    protected void tearDown() {
        super.tearDown()
    }
    void testSomething() {
    }
}

What the Test Shell Should Look Like

import grails.test.GroovyPagesTestCase
class superImportantTests extends GroovyPagesTestCase {
    //any services you will need go here
    //
    void testSomething() {

       def file = new File("grails-app/views/pathto/template.gsp")
       //when
       def result = applyTemplate(file.text, [
            //model goes here
            //key: value
       ])
       //then
       assertTrue(result.contains('something'))
    }
}

What the Test Must Have

  • The filename must end in 'Test' or 'Tests'
  • You have to extend the GroovyPagesTestCase class
  • The test(s) inside that class must be named with "test" at the beginning of the name
  • You need to provide a 'File' in the form of a path to the GSP you are testing
  • You need to send enough of a model to the template to test your feature
  • You must have an assertion

Do What Works For You!

I've just been using a local copy of an empty test as a template. But if you prefer to have Grails generate it and then you edit it that's fine too. Or if you find a better way to automate the test template tell us all!

  • It's not necessary to nest the integration tests inside an 'expense' directory

In the Expense project this is what the tests folder structure looks like:

//APPS/EXPENSE/WEB/MAIN/test

|____integration
| |____CardGspRendererTest.groovy
|____unit
| |____CardControllerTests.groovy

Test Strategies

  • If you are making a new template from scratch, make the test first so you can test drive that GSP!
  • If you are adding a test to an existing template, the following workflow works equally well.

Assertions

assertTrue(result.contains('The stuff I want'))
  • Define your desired output first.
  • It encourages you write cleaner, more testable code.
  • It should make you break your code down into more testable chunks.

Assertions Example

Given that we need receipts to open in a new window, we will need to render this for our case:

<a href="" class="icoDocument" target="_blank"></a>

Assert That it is Rendered

If this was the only 'target="_blank"' on the page we could just test for that.

assertTrue(result.contains('target="_blank"'))

The Tests Should Tell a Story

  • Start with the name of the test class

      class ReceiptAttacherTest extends...
    
  • The Services required for the test to run tell us something

      def lineItemModelService
    
  • Each test should be descriptive

      testAttachReceiptFromModal
    
  • The model you pass should be just enough to get your test to pass. It helps future developers see what the data is for.

  • You can always add comments too :)

Passing Models

In the example I've been using the GSP needs all these items to get my link to render.

     def result = applyTemplate(file.text, [
            attachReceiptOnCreate: true,
            item: [
                lineItemId: 1234,
                receipt: [
                    mediaType: 'image/jpeg',
                    originalUri: 'some/path',
                    receiptId: 5678,
                    name: 'jason'
                ]
            ]
      ])

Check for the Converse Condition

Pass a model that should NOT render the link, then...

assertFalse(result.contains('target="_blank"'))

Running the Test

mvn grails:test-app

This runs all tests

Test Output

target -> test-reports -> html

  • You can println() in your test and see the output here in the html report.

Resources

Here are links to all the assertions available: http://junit.sourceforge.net/javadoc/org/junit/Assert.html http://groovy.codehaus.org/Unit+Testing

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment