Upgrade to Pro — share decks privately, control downloads, hide ads and more …

How To Build a Test Lib for a Microservice Based Web Application with Geb & Spock

How To Build a Test Lib for a Microservice Based Web Application with Geb & Spock

At REWE digital we are building & maintaining a Microservice based e-commerce web application. Our service teams work quite autonomous & are responsible for their own services' quality. They decide which measures are appropriate & efficient in order ensure no bugs in production. Many have a reasonable code coverage via unit tests, a good lot of service tests –including UI tests– & a sufficient monitoring & alerting system.

However, several teams felt the need for a more integrated testing of the whole system to prevent CSS clashes, errors due to interface changes or eventual inconsistency disasters & many many unforeseen issues.

To support these teams, we decided turn our old retired comprehensive test suite into a test library to enable teams to write their own system tests without the need to implement every stupid step in every team.

In this talk I'd like to present our lessons learned & developed design patterns from implementing such a test library with Geb & Spock.

Demo from slide 15: https://youtu.be/JszqevCoCts
Demo from slide 19: https://youtu.be/SaDUQk3Ov8I

Michael Kutz

May 28, 2019
Tweet

More Decks by Michael Kutz

Other Decks in Technology

Transcript

  1. @MichaKutz
    @rewedigital
    @greachconf
    How to Build a Test Library
    for a Microservices-Based Web
    Application
    with Geb & Spock
    Kopenhagen, May 28th 2019

    View Slide

  2. @MichaKutz
    @rewedigital
    @greachconf

    View Slide

  3. What’s the challenge ?

    View Slide

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

    View Slide

  5. View Slide

  6. 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

    View Slide

  7. 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!!!
    No team wants it in its
    delivery pipeline

    View Slide

  8. 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

    View Slide

  9. How does it work ?

    View Slide

  10. class DemoSpec extends ReweShopSpec {
    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
    Base Spec
    Page module

    View Slide

  11. View Slide

  12. View Slide

  13. View Slide

  14. 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()
    }
    }

    View Slide

  15. class DemoSpec extends ReweShopSpec {
    ShopUserActor user = new ShopUserActor(browser, reweConfig)
    .withPickupMarketSelected()
    .withRegistered().withLoggedIn()
    def "fill basket"() {
    given:
    ShopPage shopPage = user.to(ShopPage)
    shopPage.searchFor("milch")
    when:
    shopPage.searchSuggestions.first().addToBasket()
    then:
    user.basket.readyForCheckout
    }
    }

    View Slide

  16. Are we happy ?

    View Slide

  17. ● 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!)
    ● Continuous activity allows continuous monitoring
    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

    View Slide

  18. What next ?

    View Slide

  19. browser 'chrome'
    environment 'int'
    user
    .withUniqueCredentials()
    .withRegistered()
    .withDeliveryMarketSelected()
    .withLoggedIn()
    .withBasketReadyForCheckout()

    View Slide

  20. Thank You!
    @MichaKutz
    @rewedigital
    @greachconf

    View Slide