tednaleid / grails-test-data (http://grails.org/plugin/build-test-data)
Build Test Data plugin for grails. Decorates domain objects with "build" method that will inspect constraints and automatically create and save a valid domain object. Build method takes an optional map parameter that lets the caller set values. Authors: Ted Naleid and Joe Hoover
$ hg clone http://bitbucket.org/tednaleid/grails-test-data/
Using Test Data Plugin In Your Application
Once you have the plugin installed, it should be as easy as calling build() on any of your domain objects in your tests.
If you don't pass any parameters to build, it will attempt to provide values for all of the properties that it determines have required values based on the constraints. This includes other domain objects.
If you want to specify particular values, you can pass build a map (just like you can to a domain object constructor). The plugin will attempt to create new values for any required properties that you don't specify in the map.
domainObject.build(myProperty:'myPropertyValue')
The build method default is to attempt to save the populated domain object. You can avoid saving the object first by calling the buildWithoutSave method:
domainObject.buildWithoutSave(myProperty:'myPropertyValue')
Testing the Instantiation of Your Domain Objects
If you want to try testing the build plugin on all of your domain objects to see if it'll work out of the box for you, you can create an integration test to exercise the plugin:
grails create-integration-test TestData
And putting these contents in the new test/integration/TestDataTests.groovy file:
def grailsApplication // get grails app injected into test
void testBuildAllDomains() {
def successful = true
grailsApplication.domainClasses.each { domainClass ->
println "Test of ${domainClass.name}.build()"
try {
def domainObject = domainClass.clazz.build()
assertNotNull domainObject."${domainClass.identifier.name}"
println "********** SUCCESSFUL BUILD OF $domainClass"
} catch (Exception e) {
println "********** FAILED BUILD OF $domainClass"
successful = false
}
}
assert successful
}
Working with Unique Constraints
There currently isn't built-in support for uniqueness constraints, but it's pretty easy to get this working using a closure in the config file to generate a series of unique values.
testDataConfig {
sampleData {
'com.foo.Book' {
def i = 1
title = {-> "title${i++}" } // creates "title1", "title2", ...."titleN"
}
}
}
If your test cares about this unique value, you'll likely want to reset the configuration either directly in your test or in the setUp of the test. Otherwise, other tests could have grabbed the value that you were expecting. To reset the configuration back to the original state, use this:
grails.buildtestdata.TestDataConfigurationHolder.reset()
Building Objects and Building Associated Child Objects
When you have a parent object that you want to have specific child objects, here's one way this can be done.
class Issue {
String title
static hasMany = [pages: Page]
}
class Page {
Integer number
static hasMany = [advertisments: Advertisment]
static belongsTo = [issue: Issue]
}
You can create a specific issue + pages like this:
// build the issue first
def issue = Issue.build()
// then build the pages and add them to the issue's collection
issue.pages = (1..5).collect { Page.build(issue: issue, number: it) }
assertEquals 5, issue.pages.size()
assertEquals 1, Issue.list().size() // don't build extra issues when building pages
We don't want to build the Page objects before we have the Issue otherwise the build method will create dummy issues in the database for each page (and that last assert would fail).
Assigning System Wide Default Values
Having build assign system wide default property values, or give values to classes that are "distant" in the object graph from the object you're building can all be done with the TestDataConfig configuration file.
Logging Information
If you want to see the detail of what objects the plugin is trying to save, you can set the logging level for the DomainTestDataService and the DomainInstanceBuilder to info. Just stick this line in your grails-app/conf/Config.groovy file in the log4j section
info 'grails.app.service.grails.buildtestdata.BuildTestDataService'
info 'grails.buildtestdata.DomainInstanceBuilder'
If you want to see all of the gory detail about what the plugin is doing as it traverses the object graph and examines each property, set the logging level to debug and add in the property handlers:
debug 'grails.app.service.grails.buildtestdata.BuildTestDataService'
debug 'grails.buildtestdata.DomainInstanceBuilder'
debug 'grails.buildtestdata.handler'
This revision is from 2010-01-08 23:51
