Test First, Refresh Second: Web App TDD in Grails

2,518 views
2,372 views

Published on

An introduction to the controller and domain class testing tools in the Grails Testing plugin and Grails 1.1.

Published in: Technology, Business
0 Comments
7 Likes
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total views
2,518
On SlideShare
0
From Embeds
0
Number of Embeds
299
Actions
Shares
0
Downloads
0
Comments
0
Likes
7
Embeds 0
No embeds

No notes for slide
  • Test-driven development has reached the status of received orthodoxy. For my part, I don’t object to the idea of a right way of thinking, but in our line of work, we should watch ourselves. There are some people critical of the idea of testing first, and we should listen to them.
  • One way to gauge the health of our community is to see what happens to people who don’t toe the line. We don’t want to burn them at the stake. We should listen to them. It’s especially easy to eschew testing in difficult environments, and some people do so. We should ask why.
  • Small pieces of code tested in isolation from each other. Typically at the class or method level. Often uses practices like stubbing and mocking to effect isolation. Runs fast, particularly if the IDE has a test runner that doesn’t require booting a new JVM or rebuilding the world.
  • Small pieces of code tested in isolation from each other. Typically at the class or method level. Often uses practices like stubbing and mocking to effect isolation. Runs fast, particularly if the IDE has a test runner that doesn’t require booting a new JVM or rebuilding the world.
  • Multiple units tested together in collaboration. Usually implies testing our code with a live database and servlet container. Want to test actual ORM, page rendering, service layer, etc. Runs slower. Not suitable for TDD. Should be run by a build server.
  • Multiple units tested together in collaboration. Usually implies testing our code with a live database and servlet container. Want to test actual ORM, page rendering, service layer, etc. Runs slower. Not suitable for TDD. Should be run by a build server.
  • Multiple units tested together in collaboration. Usually implies testing our code with a live database and servlet container. Want to test actual ORM, page rendering, service layer, etc. Runs slower. Not suitable for TDD. Should be run by a build server.
  • Testing features of the fully assembled system. Best to do in a story-driven fashion. Certainly slow, requires significant server infrastructure (compared to JUnit), should be run by a build server.
  • Testing features of the fully assembled system. Best to do in a story-driven fashion. Certainly slow, requires significant server infrastructure (compared to JUnit), should be run by a build server.
  • Testing features of the fully assembled system. Best to do in a story-driven fashion. Certainly slow, requires significant server infrastructure (compared to JUnit), should be run by a build server.
  • Our main concern tonight will be unit tests. You really can’t do TDD with integration or functional tests, because they take too long to run. There are two things that are important when considering unit tests.
  • These are code, not human procedures.
  • Each unit test should make assertions about a small, coherent chunk of code. Moreover, it should not matter in what order we run them. Each should be fully responsible for creating the state it needs to run its code under test.
  • Since they are executable, we should be able to have a computer run them very frequently.
  • Let’s talk about isolation some more. It’s easy—or can be—when you’re writing APIs in core Java. It’s hard in a web app. Why is that? (DB, servlet container, browser, HTTP loop)
  • Besides the web and database problems, we usually have problems related to integration points, since
  • Besides the web and database problems, we usually have problems related to integration points, since
  • Besides the web and database problems, we usually have problems related to integration points, since
  • Besides the web and database problems, we usually have problems related to integration points, since
  • Besides the web and database problems, we usually have problems related to integration points, since
  • The Testing plugin was made a part of core Grails as of the 1.1 release. It revolutionized the way we can test Grails apps.
  • These are extensions to GroovyTestCase, which is itself an extension to JUnit’s TestCase.
  • Test First, Refresh Second: Web App TDD in Grails

    1. 1. Test First, Refresh Second Test-Driven Development with Tim Berglund August, 2009
    2. 2. TDD
    3. 3. Failure to Write Tests?
    4. 4. KINDS OF TESTING
    5. 5. KINDS OF TESTING UNIT TESTING
    6. 6. KINDS OF TESTING UNIT TESTING XUNIT
    7. 7. KINDS OF TESTING
    8. 8. KINDS OF TESTING INTEGRATION TESTING
    9. 9. KINDS OF TESTING INTEGRATION TESTING XUNIT EXTENSIONS
    10. 10. KINDS OF TESTING INTEGRATION TESTING XUNIT EXTENSIONS TESTNG
    11. 11. KINDS OF TESTING
    12. 12. KINDS OF TESTING FUNCTIONAL TESTING
    13. 13. KINDS OF TESTING FUNCTIONAL TESTING
    14. 14. KINDS OF TESTING FUNCTIONAL TESTING
    15. 15. UNIT TESTS
    16. 16. EXECUTABLE
    17. 17. ISOLATED
    18. 18. AUTOMATED
    19. 19. ISOLATED?
    20. 20. WEB APP ISOLATION CHALLENGES
    21. 21. WEB APP ISOLATION CHALLENGES DATABASE
    22. 22. WEB APP ISOLATION CHALLENGES DATABASE SERVLET CONTAINER
    23. 23. WEB APP ISOLATION CHALLENGES DATABASE SERVLET CONTAINER HTTP INTERACTION
    24. 24. WEB APP ISOLATION CHALLENGES DATABASE SERVLET CONTAINER HTTP INTERACTION PAGE RENDERING
    25. 25. WEB APP ISOLATION CHALLENGES DATABASE SERVLET CONTAINER HTTP INTERACTION PAGE RENDERING ENTERPRISE INTEGRATION POINTS
    26. 26. TO THE RESCUE! (especially 1.1 and later)
    27. 27. THE GOOD STUFF
    28. 28. THE GOOD STUFF GrailsUnitTestCase ControllerUnitTestCase
    29. 29. THE GOOD STUFF
    30. 30. THE GOOD STUFF mockDomain mockController mockLogging mockConfig
    31. 31. METACLASS MAGIC
    32. 32. mockDomain
    33. 33. mockDomain SUPPORTS
    34. 34. mockDomain SUPPORTS findAll() findAllByXXX() get() read() getAll() ident() exists()
    35. 35. mockDomain SUPPORTS findAll() count() findAllByXXX() list() get() validate() read() save() getAll() delete() ident() discard() exists()
    36. 36. mockDomain
    37. 37. mockDomain DOES NOT SUPPORT
    38. 38. mockDomain DOES NOT SUPPORT Criteria Builders HQL Persistent Class Inheritance findWhere() findAllWhere()
    39. 39. mockController
    40. 40. mockController SUPPORTS
    41. 41. mockController SUPPORTS log request response session params flash
    42. 42. mockController SUPPORTS log forward() request redirect() response render() session withFormat() params withForm() flash
    43. 43. mockController
    44. 44. mockController SUPPORTS
    45. 45. mockController SUPPORTS forwardArgs redirectArgs renderArgs template modelAndView
    46. 46. mockLogging
    47. 47. mockLogging ADDS MOCKED LOG PROPERTY
    48. 48. mockLogging ADDS MOCKED LOG PROPERTY SENDS OUTPUT TO SYSTEM.OUT
    49. 49. mockLogging ADDS MOCKED LOG PROPERTY SENDS OUTPUT TO SYSTEM.OUT IGNORES DEBUG AND TRACE BY DEFAULT
    50. 50. mockLogging ADDS MOCKED LOG PROPERTY SENDS OUTPUT TO SYSTEM.OUT IGNORES DEBUG AND TRACE BY DEFAULT CAN ENABLE DEBUG WITH A SWITCH
    51. 51. mockConfig
    52. 52. mockConfig REPLACES DEFAULT GRAILS CONFIG IN grailsApplication.config
    53. 53. mockConfig REPLACES DEFAULT GRAILS CONFIG IN grailsApplication.config READS FROM A STRING
    54. 54. GrailsUnitTestCase
    55. 55. GrailsUnitTestCase INTRINSIC PROPERTIES applicationContext errorsMap INTRINSIC METHODS mockFor mockDomain mockController mockTagLib mockConfig
    56. 56. GrailsUnitTestCase MUST CALL super.setUp()!
    57. 57. ControllerUnitTestCase INTRINSIC PROPERTIES
    58. 58. ControllerUnitTestCase INTRINSIC PROPERTIES mockRequest mockResponse mockSession forwardArgs redirectArgs renderArgs mockParams mockFlash
    59. 59. ControllerUnitTestCase
    60. 60. ControllerUnitTestCase AUTOMATICALLY MOCKS CONTROLLER FROM TEST CLASS NAME
    61. 61. ControllerUnitTestCase MUST CALL super.setUp()
    62. 62. LET’S USE THIS!
    63. 63. OUR APP USER GROUP MEMBERSHIP MANAGER
    64. 64. STORIES AS AN UNREGISTERED USER, I WANT TO SIGN UP ON THE SITE.
    65. 65. STORIES AS A REGISTERED USER, I WANT TO SEE UPCOMING EVENTS.
    66. 66. STORIES AS AN ADMINISTRATOR, I WANT TO HAVE FULL CRUD CAPABILITIES ON MEETINGS.
    67. 67. STORIES AS AN ADMINISTRATOR, I WANT TO SEE WHO IS ATTENDING AN EVENT.
    68. 68. STORIES AS A REGISTERED USER, I WANT TO BE ABLE TO RSVP TO AN EVENT.
    69. 69. LIVE CODING!
    70. 70. THE CONCLUSION?
    71. 71. IT WORKS!
    72. 72. THERE ARE REAL LIMITATIONS
    73. 73. INTEGRATION AND FUNCTIONAL TESTS ARE NECESSARY
    74. 74. CREDIBLE WEB APP TDD
    75. 75. THANK YOU! TIM BERGLUND AUGUST TECHNOLOGY GROUP, LLC http://www.augusttechgroup.com tim.berglund@augusttechgroup.com @tlberglund
    76. 76. PHOTO CREDITS WELLS CATHEDRAL CHAPEL: HTTP://WWW.FLICKR.COM/PHOTOS/TASA_M/3483041197/ FIRE: HTTP://WWW.FLICKR.COM/PHOTOS/COBALT/61587166/ SHIPPING CONTAINERS: HTTP://WWW.FLICKR.COM/PHOTOS/PHOTOHOME_UK/1494590209/ COMPUTER CONSOLE: HTTP://WWW.FLICKR.COM/PHOTOS/NOSTRI-IMAGO/2910549047/

    ×