Salenda
Testing Grails 3:
the good (unit), the bad (integration) and the ugly
(functional)
Greach ’17
Alberto De Ávila Hernández
A B O U T M E
✴ Software Engineer
✴ Team Lead at Salenda
✴ Groovy y Grails dev
✴ Testing obsessed
@alberto_deavila
S A L E N D A
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
O B J E C T I V E S
@alberto_deavila
Objectives
F I R S T S T E P S
@alberto_deavila
First Steps
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
G U I D E
@alberto_deavila
✴ Testing types
✴ Testing in Grails 3
✴ Review app
✴ Unit testing
✴ Functional testing
✴ Integration testing
T E S T I N G T Y P E S
@alberto_deavila
Testing types
T E S T I N G T Y P E S
@alberto_deavila
Unit (the good)
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
T E S T I N G T Y P E S
@alberto_deavila
Integration (the bad)
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
T E S T I N G T Y P E S
@alberto_deavila
Functional (the ugly)
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
T E S T I N G I N G R A I L S 3
@alberto_deavila
Testing in Grails 3
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
T E S T I N G I N G R A I L S 3 : S P O C K
@alberto_deavila
Spock
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
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
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
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
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
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
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
R E V I E W A P P
@alberto_deavila
Review app
L E T ’ S G O T E S T
@alberto_deavila
Let’s go test!
U N I T T E S T I N G
@alberto_deavila
Unit testing
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
U N I T T E S T I N G
@alberto_deavila
Domain classes
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
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
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
U N I T T E S T I N G
@alberto_deavila
Services
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
U N I T T E S T I N G : S E R V I C E S
@alberto_deavila
Example:
ActorServiceUnitSpec
U N I T T E S T I N G : S E R V I C E S
@alberto_deavila
Exercise:
SerieServiceUnitSpec
U N I T T E S T I N G
@alberto_deavila
Controllers
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
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
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
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
F U N C T I O N A L T E S T I N G
@alberto_deavila
Functional testing
F U N C T I O N A L T E S T I N G
@alberto_deavila
API
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
F U N C T I O N A L T E S T I N G
@alberto_deavila
Example:
UserAPIFunctionalSpec
T E S T I N G I N G R A I L S 3 : G E B
@alberto_deavila
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
T E S T I N G I N G R A I L S 3 : G E B
@alberto_deavila
Pages
T E S T I N G I N G R A I L S 3 : G E B
@alberto_deavila
Test
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
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)
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
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
I N T E G R AT I O N T E S T I N G
@alberto_deavila
Integration testing
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
I N T E G R AT I O N T E S T I N G
@alberto_deavila
Domain classes
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
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
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
I N T E G R AT I O N T E S T I N G
@alberto_deavila
Services
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 ;)
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
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
I N T E G R AT I O N T E S T I N G
@alberto_deavila
Controllers
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.”
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)
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
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
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
Q U E S T I O N S
@alberto_deavila
That’s all!Thank you!!
Q U E S T I O N S
@alberto_deavila
Questions

Testing Grails 3, the goob (unit), the bad (integration) and the ugly (functional)

  • 1.
    Salenda Testing Grails 3: thegood (unit), the bad (integration) and the ugly (functional) Greach ’17 Alberto De Ávila Hernández
  • 2.
    A B OU T M E ✴ Software Engineer ✴ Team Lead at Salenda ✴ Groovy y Grails dev ✴ Testing obsessed @alberto_deavila
  • 3.
    S A LE N D A
  • 4.
    S O FT 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 JE C T I V E S @alberto_deavila Objectives
  • 6.
    F I RS T S T E P S @alberto_deavila First Steps
  • 7.
    F I RS 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 ID E @alberto_deavila ✴ Testing types ✴ Testing in Grails 3 ✴ Review app ✴ Unit testing ✴ Functional testing ✴ Integration testing
  • 9.
    T E ST I N G T Y P E S @alberto_deavila Testing types
  • 10.
    T E ST I N G T Y P E S @alberto_deavila Unit (the good)
  • 11.
    T E ST 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 ST I N G T Y P E S @alberto_deavila Integration (the bad)
  • 13.
    T E ST 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 ST I N G T Y P E S @alberto_deavila Functional (the ugly)
  • 15.
    T E ST 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 ST I N G I N G R A I L S 3 @alberto_deavila Testing in Grails 3
  • 17.
    T E ST 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 ST I N G I N G R A I L S 3 : S P O C K @alberto_deavila Spock
  • 19.
    T E ST 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 ST I N G I N G R A I L S 3 : S P O C K @alberto_deavila Describe test
  • 21.
    T E ST 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 ST 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 ST 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 ST I N G I N G R A I L S 3 : S P O C K @alberto_deavila Fixture methods
  • 25.
    T E ST 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
  • 26.
    R E VI E W A P P @alberto_deavila Review app
  • 27.
    L E T’ S G O T E S T @alberto_deavila Let’s go test!
  • 28.
    U N IT T E S T I N G @alberto_deavila Unit testing
  • 29.
    U N IT 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 IT T E S T I N G @alberto_deavila Domain classes
  • 31.
    U N IT 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 IT 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 IT 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 IT T E S T I N G @alberto_deavila Services
  • 35.
    U N IT 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 IT T E S T I N G : S E R V I C E S @alberto_deavila Example: ActorServiceUnitSpec
  • 37.
    U N IT T E S T I N G : S E R V I C E S @alberto_deavila Exercise: SerieServiceUnitSpec
  • 38.
    U N IT T E S T I N G @alberto_deavila Controllers
  • 39.
    U N IT 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 IT 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 IT 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 IT 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 NC T I O N A L T E S T I N G @alberto_deavila Functional testing
  • 44.
    F U NC T I O N A L T E S T I N G @alberto_deavila API
  • 45.
    F U NC 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 NC T I O N A L T E S T I N G @alberto_deavila Example: UserAPIFunctionalSpec
  • 47.
    T E ST I N G I N G R A I L S 3 : G E B @alberto_deavila
  • 48.
    T E ST 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 ST I N G I N G R A I L S 3 : G E B @alberto_deavila Pages
  • 50.
    T E ST I N G I N G R A I L S 3 : G E B @alberto_deavila Test
  • 51.
    F U NC 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 NC 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 IT 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 IT 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 TE G R AT I O N T E S T I N G @alberto_deavila Integration testing
  • 56.
    I N TE 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 TE G R AT I O N T E S T I N G @alberto_deavila Domain classes
  • 58.
    I N TE 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 TE 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 TE 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 TE G R AT I O N T E S T I N G @alberto_deavila Services
  • 62.
    I N TE 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 TE 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 TE 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 TE G R AT I O N T E S T I N G @alberto_deavila Controllers
  • 66.
    I N TE 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 TE 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 TE 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 TE 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 TE 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 ES T I O N S @alberto_deavila That’s all!Thank you!!
  • 72.
    Q U ES T I O N S @alberto_deavila Questions