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

Having Our Cake and Eating It at CukeUp 2017

Having Our Cake and Eating It at CukeUp 2017

Presented at CukeUp 2017

Video: https://www.youtube.com/watch?v=Fk4rCn4YLLU

5358df52bd2ef4f57da1b1cc8634cfd9?s=128

Nat Pryce

June 23, 2017
Tweet

Transcript

  1. End-to-end functional tests that can run in milliseconds Having Our

    Cake & Eating It Nat Pryce
  2. A familiar story...

  3. We needed a new approach Developers responsible for all test

    automation QA responsible for manual, exploratory & qualitative testing Automated functional tests written in terms of the domain model, not the user interface
  4. The Hexagonal architecture AKA Ports & Adaptors HTTP service f

    Adaptor layer maps from technical domain to application domain, but does no business logic.
  5. Invert the Hexagonal architecture HTTP service Test driver f -1

    Test f
  6. Virtual Machine Virtual Machine Virtual Machine Similarly, at wider scales...

    Test driver f -1 Test Load balancer f Firewall
  7. Service cluster Service cluster Front-end cluster Front-end cluster Service cluster

    ...and wider Test driver (g∘f) -1 Test Front-end cluster Web browser f g
  8. Data centre Data centre Data centre ...and wider Test driver

    Test f (g∘f) -1 g Web browser CDN
  9. Scenario Turn the Screenplay metaphor up to eleven! Actor Role

    Tasks Domain Model Behind the scenes Visible in test code System under test Production System Interface Plays Acts upon Acts upon Creates Involves Performs Defined in terms of Defines
  10. Example @Test fun `An editor can request an amendment`() {

    val scenario = theProduction.newScenario() val alice = scenario.newAuthor() val ed = scenario.newEditorialStaffMember() val submissionDetails = exampleSubmission.withSingleAuthor(alice) val initialSubmission = alice.hasSubmitted(submissionDetails) val amendment = ed.canRequestAmendmentOf(initialSubmission) alice.canReview(amendment, expectedContents = submissionDetails.withStatus(IN_PROGRESS)) alice.canUpdate(amendment, SetTitle("a new title"), SubmitToPeerReview) ed.canSeeInThePeerReviewSystem(amendment, status = RECEIVED) }
  11. Benefits Same test code can run quickly against the domain

    model, or more slowly against different deployments of the system Tests are quick to write • Concise • Type safe • IDE support: navigation, auto-complete, refactoring, etc. Tests are easy to read • Concise • No user-interface and technical details No duplication in test code or between test & production code
  12. Some challenges

  13. 1. Unfamiliar: How to approach TDD? Inside-out? Outside-in?

  14. 1. How to approach TDD? Inside-out? Outside-in? Both!

  15. 2. Combinatorial explosion of mappings Add Author Remove Author Set

    Affiliation Set Title & Abstract Submit to Review Domain Model Service API Browser (with JS) Browser (no JS)
  16. 2. Apply the Lingua Franca Pattern! Add Author Remove Author

    Set Affiliation Set Title & Abstract Submit to Review Domain Model Service API Browser (with JS) Browser (no JS) User Actions
  17. 3. Multiple possible mappings Can map from action to user

    action in multiple ways • Different ways to navigate through the user interface • Different ways to upload files • Keyboard vs mouse input • JavaScript vs no JavaScript Approaches: • Choose randomly on each run ◦ A form of property test • Ensure equivalence with unit tests and exercise only one in the functional tests
  18. Q: Why system tests? What about the testing pyramid?

  19. Test-drive at the system scale

  20. To test the system we need to... know what the

    system is doing know when it has stopped doing it know when the system has failed explain what has gone wrong restore the system to a good state
  21. To test the system we need to... support know what

    the system is doing know when it has stopped doing it know when the system has failed explain what has gone wrong restore the system to a good state
  22. The End