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

Internal Talk - Test Design and Software Archit...

Internal Talk - Test Design and Software Architecture

This internal talk discusses the relationship between test design and software architecture, focusing on how they enhance maintainability and development efficiency. It emphasizes the importance of creating tests that are representative, simple, stable, and cost-effective, with a focus on balancing test coverage with efficiency. The software architecture should define clear boundaries, separate stable from volatile parts, and protect against unnecessary changes. Tests are part of the system and should be designed to ensure they only break when intended, contributing to better developer experience and maintainability.

Avatar for Marc Neureiter

Marc Neureiter

March 12, 2024
Tweet

More Decks by Marc Neureiter

Other Decks in Programming

Transcript

  1. REPRESENTATIVE A test should be representative: it gives confidence that

    our product really works. Prefer component/broad stack tests Aim for high coverage
  2. SIMPLE A test should be easy to understand Don't test

    too much of the system Humble object pattern → no need to test Structure Proper naming Separate the what from the how (abstraction) Use arrange/act/assert (AAA) and given/when/then
  3. STABLE A test should only break when you change the

    behavior under test Avoid needing to change a test at the same time as production code Don't test too much into the system's depth Test the same API production code is using (black box) Keep the API stable Or wrap it with a testing API Use DI framework to assemble dependencies
  4. CHEAP AND FAST Testing should be cheap (= fast to

    write, read, run and modify) Don't test too much of the system Don't test too much of the cases Don't aim for high coverage Focus on where it is likely to break Make it run fast and often
  5. ROI Compromise ist the only way Scope, integration level and

    boundaries unit, component, integration, broad-stack, full-stack business logic / adapter logic (data layer, view layer) Cases / coverage Fast run time (Robolectric)
  6. CONCLUSIONS We already use architectural patterns It costs time up

    front It has real life positive impact There are underlying principles
  7. SOFTWARE ARCHITECTURE 🤨 ...is what makes software able to change

    ...is the part in software that does not change building metaphor: supporting walls vs. non-supporting walls
  8. HOW? Define responsibilities/boundaries (SRP) Tell apart high-level policies from implementation

    details (DIP) Define what's volatile and what's stable (DIP, OCP) Protect stuff from change (OCP)
  9. RESPONSIBILITY → BOUNDARY = reason to change (actors, e.g. business

    vs. design) = technology vs. business (axis of change) = time or frequency of change Source: Microsoft
  10. STABILITY VS. VOLATILITY When something can be expected to change,

    it's volatile. If not, it's stable. Tests should be stable, the system under test may be not.
  11. PROTECT STUFF FROM CHANGE Don't depend on anything volatile (TBD:

    and concrete across components/modules) Prevent dependency on stuff too much lower-level / implementation details Prevent changes from unrelated reasons to change
  12. THE SUPERPOWERS Turn around the dependency (DIP, TBD) Abstraction (OCP,

    some things TBD) On all levels: methods, classes, files, components, modules
  13. HOW IS THIS ALL RELATED? It's not only the code

    itself that makes it hard to change but who depends on it in the system Tests are part of the system Tests depend on your production code Tests are part of the cruft and need to be considered Cruft → Maintainability → Developer Experience + open options Maintainability is the first thing to reason about in software designs
  14. CODING EXAMPLE Responsibilities, boundaries, reason to change (time vs. space,

    or actor (mobile lead, PO), technology vs. business) Volatile (VM) vs. stable (testing API) / non-supporting walls vs. supporting walls Dependencies: business → testing API → VM Component tests vs. broad-stack vs. unit tests (understandability, maintainability, representativeness)
  15. EXERCISE Try out implementing a feature step by step Implement

    each step as if there was only that step Have tests in place from the start (not at the end) See how easy the test breaks and think about how you can achieve that it only breaks in the places intended
  16. RECAP Don't get used to how hard the code is

    to change Don't get too much annoyed about up-front work When changing or refactoring something, make sure you have a test that secures the behavior Tests guide development and design, but only if they are not too much cruft Reason about architecture and include testing Complex, contradictory; a journey... You're not responsible for following recipes but for the RoI