Successfully reported this slideshow.
Your SlideShare is downloading. ×

Grails build-test-data Plugin

Ad

grails
                         build-test-data
                             plugin




                         created b...

Ad

creating test data with
                            groovy is easy!


Tuesday, July 14, 2009

Ad

iterators
                                     ["Alice", "Bob", "Carol", "Dave"].each {
                         closures ...

Ad

Ad

Ad

Ad

Ad

Ad

Ad

Ad

Ad

Ad

Ad

Ad

Ad

Ad

Ad

Ad

Ad

Ad

Ad

Ad

Ad

Ad

Ad

Ad

Ad

Ad

Ad

Ad

Ad

Ad

Ad

Ad

Ad

Ad

Ad

Ad

Ad

Ad

Ad

Ad

Ad

Ad

Upcoming SlideShare
Spock and Geb
Spock and Geb
Loading in …3
×

Check these out next

1 of 45 Ad
1 of 45 Ad

Grails build-test-data Plugin

Download to read offline

Presentation on the grails build-test-data plugin. Shows how much easier test data can be created, and how much more readable your tests are when you only need to specify the things you actually care about.

See: http://bitbucket.org/tednaleid/grails-test-data/wiki/Home
Blog: http://naleid.com/blog/2009/04/14/grails-build-test-data-01-plugin-released/

Presentation on the grails build-test-data plugin. Shows how much easier test data can be created, and how much more readable your tests are when you only need to specify the things you actually care about.

See: http://bitbucket.org/tednaleid/grails-test-data/wiki/Home
Blog: http://naleid.com/blog/2009/04/14/grails-build-test-data-01-plugin-released/

Advertisement
Advertisement

More Related Content

Advertisement

Grails build-test-data Plugin

  1. 1. grails build-test-data plugin created by Ted Naleid and Joe Hoover Tuesday, July 14, 2009
  2. 2. creating test data with groovy is easy! Tuesday, July 14, 2009
  3. 3. iterators ["Alice", "Bob", "Carol", "Dave"].each { closures } new Author(name: it).save() syntactic sugar Tuesday, July 14, 2009
  4. 4. modeling your domain in grails is easy! Tuesday, July 14, 2009
  5. 5. a book belongs class Book { String title static belongsTo = [author: Author] to an author } an author has class Author { String name many books } static hasMany = [books: Book] Tuesday, July 14, 2009
  6. 6. class User { String login String password String email Date birthDate static constraints = { login(size: 5..15, constraints blank: false, unique: true) password(size: 5..15, blank: false) email(email: true, blank: false) birthDate(max: new Date()) } } Tuesday, July 14, 2009
  7. 7. test data must pass constraints def user = new User( login: “tnaleid”, password: “sekrit1”, birthDate: new Date() - (365 * 36) ).save() Tuesday, July 14, 2009
  8. 8. whoops! missed an attribute! def user = new User( login: “tnaleid”, password: “sekrit1”, email: “contact@naleid.com”, age: new Date() - (365 * 36) ).save() Tuesday, July 14, 2009
  9. 9. constrained attributes are required even if your test doesn’t care about them def user = new User( login: “tnaleid”, password: “sekrit”, email: “contact@naleid.com”, birthDate: new Date() - (365 * 36) ).save() // service looks up user in DB by username and deletes it assertTrue userService.deleteByUsername(“tnaleid”) Tuesday, July 14, 2009
  10. 10. problem multiplied by complex domain models Tuesday, July 14, 2009
  11. 11. agile + code coverage = lots of tests Tuesday, July 14, 2009
  12. 12. you need to add a new constraint... what happens to all the tests? Tuesday, July 14, 2009
  13. 13. Tuesday, July 14, 2009
  14. 14. creating maintainable test data is hard! Tuesday, July 14, 2009
  15. 15. existing test data creation strategies Tuesday, July 14, 2009
  16. 16. void testTenDollarPurchase() { def author = new Author( name: “David Foster Wallace” ).save() Book book = new Book( author: author, title: "The Pale King", published: new Date(), price: 10.00 as BigDecimal ).save()   copy/paste/ } def ord = service.orderBook(book.id)  //... test assertions modify for every void testTwentyDollarPurchase() { test method def author = new Author( name: “David Foster Wallace” ).save() Book book = new Book( author: author, title: "Infinite Jest", published: new Date(), price: 20.00 as BigDecimal ).save()   def ord = service.orderBook(book.id)  //... test assertions } Tuesday, July 14, 2009
  17. 17. def author void setUp() { author = new Author( name: “David Foster Wallace” ).save() } void testTenDollarPurchase() { Book book = new Book( author: author, title: "The Pale King", use setUp method published: new Date(), price: 10.00 as BigDecimal ).save() to share objects   def order = service.orderBook(book.id)  across tests } //... test assertions void testTwentyDollarPurchase() { Book book = new Book( author: author, title: "Infinite Jest", published: new Date(), price: 20.00 as BigDecimal ).save()   def result = service.orderBook(book.id)  //... test assertions } Tuesday, July 14, 2009
  18. 18. class AuthorObjectMother { static dfw() { return new Author( name: “David Foster Wallace” ).save() } } class BookObjectMother { static thePaleKing() { return new Book( author: AuthorObjectMother.dfw(), title: “The Pale King”, published: new Date(), price: 10.00 as BigDecimal ).save() object mother } static infiniteJest() { return new Book( author: AuthorObjectMother.dfw(), pattern title: “Infinite Jest”, published: new Date(), price: 20.00 as BigDecimal ).save() } } testTenDollarPurchase() {  Book book = BookObjectMother.thePaleKing() def result = service.orderBook(book.id)  //... test assertions } void testTwentyDollarPurchase() { Book book = BookObjectMother.infiniteJest()  def result = service.orderBook(book.id)  //... test assertions } Tuesday, July 14, 2009
  19. 19. // fixtures/dfwBooks.groovy: fixture { davidFosterWallace(Author) { name = “David Foster Wallace” } thePaleKing(Book) { author = davidFosterWallace title = "The Pale King" published = new Date() price = 10.00 as BigDecimal } infiniteJest(Book) { author = davidFosterWallace title = "Infinite Jest" published = new Date() builder DSL / test } } price = 20.00 as BigDecimal fixtures // test class ... def fixtureLoader void testTenDollarPurchase() { fixtureLoader.load("dfwBooks") Book book = Book.findByTitle(“The Pale King”) def result = service.orderBook(book.id)  //... test assertions } void testTenDollarPurchase() { fixtureLoader.load("dfwBooks") Book book = Book.findByTitle(“Infinite Jest”) def result = service.orderBook(book.id)  //... test assertions } Tuesday, July 14, 2009
  20. 20. all of these strategies strive to DRY up your test data creation Tuesday, July 14, 2009
  21. 21. but all of them repeat the same rules specified in the constraints Tuesday, July 14, 2009
  22. 22. void testTenDollarPurchase() { Book book = new Book( price: 10.00 as BigDecimal ) mockDomain(Book, [book]) grails does have def order = service.orderBook(book.id) //...test assertions mocks ... but what } are they really void testTwentyDollarPurchase() { Book book = new Book( testing? ) price: 20.00 as BigDecimal mockDomain(Book, [book])   def result = service.orderBook(book)  //... test assertions } Tuesday, July 14, 2009
  23. 23. void testPurchaseBookService() { def author = new Author( name: "First Last", ).save() Book book = new Book( what if we could author: author, title: "title", published: new Date(), turn this price: 10.00 as BigDecimal ).save()   def order = service.orderBook(book.id) //... test assertions } void testPurchaseBookService() { Book book = Book.build( price: 10.00 as BigDecimal into this ) def result = service.orderBook(book) //... test assertions } Tuesday, July 14, 2009
  24. 24. you can with the build-test-data plugin Tuesday, July 14, 2009
  25. 25. build-test-data advantages Tuesday, July 14, 2009
  26. 26. testing data documents what’s being tested Tuesday, July 14, 2009
  27. 27. only specify values the test uses Tuesday, July 14, 2009
  28. 28. test coupling is eliminated Tuesday, July 14, 2009
  29. 29. you’re executing real GORM code paths Tuesday, July 14, 2009
  30. 30. unrelated domain changes won’t break your tests Tuesday, July 14, 2009
  31. 31. build-test-data usage Tuesday, July 14, 2009
  32. 32. class Author { String name static hasMany = [books: Book] } our domain class Book { String title static belongsTo = [author: Author] } Tuesday, July 14, 2009
  33. 33. just give me a def book = Book.build() assertNotNull book.author book assertNotNull book.title Tuesday, July 14, 2009
  34. 34. give me a book, but let me set the def book = Book.build(title:“Infinite Jest”) title Tuesday, July 14, 2009
  35. 35. let me tweak the def book = Book.build(author: ) Author.build(name: “Charlie Stross”) book’s author Tuesday, July 14, 2009
  36. 36. build-test-data features Tuesday, July 14, 2009
  37. 37. ‣ Domain objects (1..1, 1..N, N..N) ‣ Embedded domain objects build-test-data ‣ ‣ String Boolean supports all ‣ ‣ Number (Integer, Long, Float, etc) Byte known attribute ‣ Date types ‣ ‣ Enum JodaTime ‣ Any other hibernate persistable class with a zero-argument constructor Tuesday, July 14, 2009
  38. 38. ‣ nullable ‣ blank ‣ inList ‣ max ‣ maxSize automatic ‣ ‣ min minSize constraint support ‣ ‣ range scale ‣ size ‣ url ‣ creditCard ‣ email Tuesday, July 14, 2009
  39. 39. manual constraint ‣ ‣ matches (regular expressions) validator (user-defined constraint) support ‣ unique Tuesday, July 14, 2009
  40. 40. configuration file lets you customize static attribute values // grails-app/conf/TestDataConfig.groovy testDataConfig { sampleData = { Publisher { name = “Pragmatic Bookshelf” // default unless overridden } } } Tuesday, July 14, 2009
  41. 41. configuration file lets you customize dynamic attribute values // grails-app/conf/TestDataConfig.groovy testDataConfig { sampleData = { ‘com.example.Hotel’ { def i = 1 name = {-> “name${i++}” } // “name1”, “name2”, ... “nameN” } } } Tuesday, July 14, 2009
  42. 42. build-test-data installation grails install-plugin build-test-data Tuesday, July 14, 2009
  43. 43. live coding demo Tuesday, July 14, 2009
  44. 44. links build-test-data home http://bitbucket.org/tednaleid/grails-test-data/wiki/Home intro blog post http://naleid.com/blog/2009/04/14/grails-build-test-data-01-plugin-released/ photo credits http://www.flickr.com/photos/kaptainkobold/3406169798/in/set-1058884 http://commons.wikimedia.org/wiki/File:Domain_model.png http://www.flickr.com/photos/nickwheeleroz/2474196275/in/photostream Tuesday, July 14, 2009
  45. 45. Questions? Tuesday, July 14, 2009

×