- About Me
- These are Integration Tests
- How I Think About Tests
- Anatomy of a Test
- Assertions
- Passing Models
- Running the Test
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
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.
- 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...
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"'))
}
}
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() {
}
}
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'))
}
}
- 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
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
- 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.
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.
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>
If this was the only 'target="_blank"' on the page we could just test for that.
assertTrue(result.contains('target="_blank"'))
-
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 :)
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'
]
]
])
Pass a model that should NOT render the link, then...
assertFalse(result.contains('target="_blank"'))
mvn grails:test-app
This runs all tests
target -> test-reports -> html
- You can println() in your test and see the output here in the html report.
Here are links to all the assertions available: http://junit.sourceforge.net/javadoc/org/junit/Assert.html http://groovy.codehaus.org/Unit+Testing