Code available at: https://github.com/albertodeavila/testingGrails3
Do you want to know how to testing Grails 3 apps? Here you will find the following:
- Unit test
- Integration test
- Functional test
All of these, using Spock, Geb, Groovy, Grails and Gradle.
4. S O F T WA R E D E V E L O P M E N T
Turnkey
development
Gold
Atlassian
Solution
Partner
Consulting and
support in
software
architecture and
analysis
Application
integration
Evolutionary support
of our own
developments or
inherited ones
@alberto_deavila
5. O B J E C T I V E S
@alberto_deavila
Objectives
6. F I R S T S T E P S
@alberto_deavila
First Steps
7. F I R S T S T E P S
@alberto_deavila
✴ Install Java 8
✴ Install sdkman
>$ curl -s "https://get.sdkman.io" | bash
>$ source "$HOME/.sdkman/bin/sdkman-init.sh"
✴ Install Grails 3.2.6
>$ sdk install grails 3.2.6
✴Clone: github.com/albertodeavila/testingGrails3
8. G U I D E
@alberto_deavila
✴ Testing types
✴ Testing in Grails 3
✴ Review app
✴ Unit testing
✴ Functional testing
✴ Integration testing
9. T E S T I N G T Y P E S
@alberto_deavila
Testing types
10. T E S T I N G T Y P E S
@alberto_deavila
Unit (the good)
11. T E S T I N G T Y P E S : U N I T
@alberto_deavila
✴ Test a small piece of code
✴ Simulate the rest of pieces
✴ Mock it
✴ Override behavior
✴ Independents on the environment
✴ Very quickly
12. T E S T I N G T Y P E S
@alberto_deavila
Integration (the bad)
13. T E S T I N G T Y P E S : I N T E G R AT I O N
@alberto_deavila
✴ Test a complete functionality
✴ Start the app
✴ Test inside the app
✴ Slow
✴ Depends on the environment
14. T E S T I N G T Y P E S
@alberto_deavila
Functional (the ugly)
15. T E S T I N G T Y P E S : F U N C T I O N A L
@alberto_deavila
✴ Test a complete functionality as a user
✴ Start the app
✴ Test outside the app
✴ Browsing the app / calling API
✴ Slow
✴ Not cross browser and some browser errors
16. T E S T I N G I N G R A I L S 3
@alberto_deavila
Testing in Grails 3
17. T E S T I N G I N G R A I L S 3
@alberto_deavila
✴ Plugins:
✴ Build test-data plugin
✴ Greenmail
✴ Rest client builder
✴ Spock
✴ Geb
18. T E S T I N G I N G R A I L S 3 : S P O C K
@alberto_deavila
Spock
19. T E S T I N G I N G R A I L S 3 : S P O C K
@alberto_deavila
✴ Describe test
✴ Blocks
✴ Mocks
✴ Data tables
✴ Fixture methods
✴ Tricks and recomendations
20. T E S T I N G I N G R A I L S 3 : S P O C K
@alberto_deavila
Describe test
21. T E S T I N G I N G R A I L S 3 : S P O C K
@alberto_deavila
✴ Given / Setup: preconditions and data
✴ Cleanup: postconditions
✴ When: action that trigger some outcome
✴ Then / Expect: assert outcome
✴ Where: applies varied data
Blocks
22. T E S T I N G I N G R A I L S 3 : S P O C K
@alberto_deavila
✴ Given, Expect
✴ Given, When, Then
✴ Given, When, Then, Where, Cleanup
✴ Given, Expect, Where
✴ When, Then, Where, Cleanup
Blocks: samples
23. T E S T I N G I N G R A I L S 3 : S P O C K
@alberto_deavila
Mocks Data tables
24. T E S T I N G I N G R A I L S 3 : S P O C K
@alberto_deavila
Fixture methods
25. T E S T I N G I N G R A I L S 3 : S P O C K
@alberto_deavila
✴ Use assert if there are { } in then clause
✴ You can catch exceptions with thrown
✴ @Build includes @Mock
✴ Use .buildWithoutSave() to avoid persist
✴ Use @ConfineMetaClassChanges ;)
Tricks & recommendations
27. L E T ’ S G O T E S T
@alberto_deavila
Let’s go test!
28. U N I T T E S T I N G
@alberto_deavila
Unit testing
29. U N I T T E S T I N G
@alberto_deavila
✴ Unit test extends Specification
✴ @TestFor annotation to indicate what test
✴ @Mock annotation to simulate another entity
✴ @Build annotation to create default entities
30. U N I T T E S T I N G
@alberto_deavila
Domain classes
31. U N I T T E S T I N G : D O M A I N C L A S S E S
@alberto_deavila
✴ @TestFor with the domain class to test
✴ Check constraints and logic in domain class
✴ Implicit variable domain
✴ Tricks:
✴ Use the @Unroll to use different data
✴ Persistence can’t be tested with unit test
32. U N I T T E S T I N G : D O M A I N C L A S S E S
@alberto_deavila
Example:
EpisodeUnitSpec
33. U N I T T E S T I N G : D O M A I N C L A S S E S
@alberto_deavila
Exercise:
SerieUnitSpec
34. U N I T T E S T I N G
@alberto_deavila
Services
35. U N I T T E S T I N G : S E R V I C E S
@alberto_deavila
✴ Again @TestFor annotation
✴ Implicit variable service
✴ defineBeans: to inject services / beans
✴ Override method:
✴ Metaclass
✴ Mock
36. U N I T T E S T I N G : S E R V I C E S
@alberto_deavila
Example:
ActorServiceUnitSpec
37. U N I T T E S T I N G : S E R V I C E S
@alberto_deavila
Exercise:
SerieServiceUnitSpec
38. U N I T T E S T I N G
@alberto_deavila
Controllers
39. U N I T T E S T I N G : C O N T R O L L E R S
@alberto_deavila
✴ Implicit variable controller
✴ Helpers: view / model / response
✴ defineBeans: to inject services / beans
✴ If action return a map, model & view are null
✴ Save the action call return in a variable
✴ Bug: view doesn’t contains the template
40. U N I T T E S T I N G : C O N T R O L L E R S
@alberto_deavila
Example:
UserControllerUnitSpec
41. U N I T T E S T I N G : C O N T R O L L E R S
@alberto_deavila
Exercise:
ActorControllerUnitSpec
42. U N I T T E S T I N G : C O N T R O L L E R S
@alberto_deavila
Exercise:
SerieControllerUnitSpec
43. F U N C T I O N A L T E S T I N G
@alberto_deavila
Functional testing
44. F U N C T I O N A L T E S T I N G
@alberto_deavila
API
45. F U N C T I O N A L T E S T I N G
@alberto_deavila
✴ To test APIs you can use RestBuilder
✴ Use authentication
✴ Parse JSON / XML responses
46. F U N C T I O N A L T E S T I N G
@alberto_deavila
Example:
UserAPIFunctionalSpec
47. T E S T I N G I N G R A I L S 3 : G E B
@alberto_deavila
48. T E S T I N G I N G R A I L S 3 : G E B
@alberto_deavila
✴ Define:
✴ Pages: elements with jQuery style
selectors
✴ Modules: reuse content
✴ Create test to navigate through app
✴ Check content visible in browser
49. T E S T I N G I N G R A I L S 3 : G E B
@alberto_deavila
Pages
50. T E S T I N G I N G R A I L S 3 : G E B
@alberto_deavila
Test
51. F U N C T I O N A L T E S T I N G
@alberto_deavila
✴ Functional test extends GebSpec
✴ You can use beans with @Autowired
✴ To create data: Entity.withNewSession
✴ @Stepwise to execute test depending on
the previous
52. F U N C T I O N A L T E S T I N G
@alberto_deavila
✴ To execute JS code: js.exec(“alert(‘hi’)“)
✴ Go to some URL with: go(URL)
✴ Go to some Page defined: to SomePage
✴ Check if we are at a Page: at SomePage
✴ Use waitFor to ensure content is loaded
✴ To define Optional content: (required: false)
53. U N I T T E S T I N G : C O N T R O L L E R S
@alberto_deavila
Example:
UserFunctionalSpec
54. U N I T T E S T I N G : C O N T R O L L E R S
@alberto_deavila
Exercise:
SerieFunctionalSpec
55. I N T E G R AT I O N T E S T I N G
@alberto_deavila
Integration testing
56. I N T E G R AT I O N T E S T I N G
@alberto_deavila
✴ Functional test extends Specification
✴ Mark @Integration to differentiate from unit
✴ Like functional: use services with
@Autowired
✴ You don’t need to use @Build annotation
57. I N T E G R AT I O N T E S T I N G
@alberto_deavila
Domain classes
58. I N T E G R AT I O N T E S T I N G : D O M A I N C L A S S E S
@alberto_deavila
✴ Very similar to unit test
✴ You don’t need to mock domain classes :)
✴ You can check database persistence and
integrity
✴ Remember to Delete your created data or
use @Rollback
59. I N T E G R AT I O N T E S T I N G : D O M A I N C L A S S E S
@alberto_deavila
Example:
UserIntegrationSpec
60. I N T E G R AT I O N T E S T I N G : D O M A I N C L A S S E S
@alberto_deavila
Exercise:
EpisodeIntegrationSpec
61. I N T E G R AT I O N T E S T I N G
@alberto_deavila
Services
62. I N T E G R AT I O N T E S T I N G : S E R V I C E S
@alberto_deavila
✴ Define services with @Autowired
✴ Use it ;)
63. I N T E G R AT I O N T E S T I N G : S E R V I C E S
@alberto_deavila
Example:
SerieServiceIntegrationSpec
64. I N T E G R AT I O N T E S T I N G : S E R V I C E S
@alberto_deavila
Exercise:
UserServiceIntegrationSpec
65. I N T E G R AT I O N T E S T I N G
@alberto_deavila
Controllers
66. I N T E G R AT I O N T E S T I N G : C O N T R O L L E R S
@alberto_deavila
Grails docs:
“To integration test controllers it is recommended
you use create-functional-test command to create a
Geb functional test.”
67. I N T E G R AT I O N T E S T I N G : C O N T R O L L E R S
@alberto_deavila
✴ @Autowire Controller instance
✴ Define a bean WebApplicationContext
✴ To allow make request GrailsWebMockUtil.
bindMockWebRequest (context)
68. I N T E G R AT I O N T E S T I N G : C O N T R O L L E R S
@alberto_deavila
✴If action make redirect, ensure you have
controller specified
✴ Use modelAndView to obtain
✴ View name
✴ Renderer data
69. I N T E G R AT I O N T E S T I N G : C O N T R O L L E R S
@alberto_deavila
Example:
SerieControllerIntegrationSpec
70. I N T E G R AT I O N T E S T I N G : C O N T R O L L E R S
@alberto_deavila
Exercise:
UserControllerIntegrationSpec
71. Q U E S T I O N S
@alberto_deavila
That’s all!Thank you!!