Slide 1

Slide 1 text

@MichaKutz @rewedigital @greachconf How to Build a Test Library for a Microservices-Based Web Application with Geb & Spock Madrid, March 30th 2019

Slide 2

Slide 2 text

@MichaKutz @rewedigital @greachconf

Slide 3

Slide 3 text

What’s the challenge ?

Slide 4

Slide 4 text

> 25 teams > 150 services composition of micro-frontends deployment at will

Slide 5

Slide 5 text

No content

Slide 6

Slide 6 text

Simple unit tests are easy Testing a single service is easy… but contract tests are hard due to asynchronous communication Fully integrated system tests seem necessary, but are hard ⇒ not done by most teams Requires a test system Requires a built service Requires code only

Slide 7

Slide 7 text

Each team writes functional test that matter most to them Test suite grows bigger and bigger… …test runs take longer and longer Nobody is responsible for the suite as a whole …up to 3 hours!!!

Slide 8

Slide 8 text

Page Objects for every relevant page Further code to navigate around the application Base test class for basic test setup Test environment configuration Test fixtures (accounts, products, addresses) Geb configuration for needed browsers “Hacks” to manipulate the application

Slide 9

Slide 9 text

How does it work ?

Slide 10

Slide 10 text

ShopUserActor user = new ShopUserActor(browser, reweConfig) .withPickupMarketSelected() .withInvoiceAddress(Address.COLOGNE) .withRegistered() .withLoggedIn() .withWindowSize(1280, 768) def "fill basket"() { given: ShopPage shopPage = user.to(ShopPage) shopPage.searchFor("milch") when: shopPage.searchSuggestions.first().addToBasket() then: user.basket.readyForCheckout } Test Actor Test system configuration Basic setup (using hacks) Test fixture Page object Verification via service client

Slide 11

Slide 11 text

ShopUserActor

Slide 12

Slide 12 text

Avoid the God pattern with Traits

Slide 13

Slide 13 text

Page Objects

Slide 14

Slide 14 text

Abstraction levels Tests use case language Page Objects page structure Test Actor workflow language def "fill basket"() { when: user.login() then: user.loggedIn } void logout() { ShopPage shopPage = to ShopPage shopPage.logoutLink.click() } class LoginPage extends Page { static url = "/mydata/login" LoginFormModule getLoginForm() { $("form#loginForm") .module(LoginFormModule) } String getErrorMessage() { $(".error-block")?.text() } }

Slide 15

Slide 15 text

Are we happy ?

Slide 16

Slide 16 text

● Every single team can easily product high level fully integrated system tests ● Tests are executed within the CI/CD cycles of the teams and services ● Test actor keeps tests very readable & maintainable ● Minimized common test suite to monitor test system (service deployments are not the only source of defects!) Conclusion ● Teams still need to keep the library up to date when pages or workflows change ● Keeping test fixtures in sync with the test system is a huge challenge ● Keeping the code base small and maintainable is sometimes hard Good Could be better

Slide 17

Slide 17 text

Thank You! @MichaKutz @rewedigital @greachconf https://greach.contestia.es/ Please leave feedback at