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

Preview:

Citation preview

SalendaTesting 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 W A 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