FSD Frontend System Design

Part II β€” The Shield Β· Lesson 4.6

Test-Driven Development

In one lineWrite the failing test first β€” it forces you to design the interface before the implementation.

Where you've seen itBuilding a usePagination hook. Writing the test first makes you decide what it returns before you decide how it works.

  • Time14 min
  • DiagramRed β†’ green β†’ refactor cycle
  • Chapter4 Β· Testing

Diagram

diagram
THE CYCLE β€” minutes per lap, not hours

        β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
        β”‚  1. RED          β”‚  write the smallest failing test
        β”‚  it must fail    β”‚  ← if it passes, it tests nothing
        β””β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                 β–Ό
        β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
        β”‚  2. GREEN        β”‚  simplest code that passes
        β”‚  ugly is fine    β”‚  ← hardcoding is allowed here
        β””β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                 β–Ό
        β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
        β”‚  3. REFACTOR     β”‚  clean up, tests stay green
        β”‚  no new behaviourβ”‚  ← the safety net you just built
        β””β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                 β”‚
                 └──────────► next case
diagram
WHY "RED FIRST" IS NOT CEREMONY

  test written AFTER code   β†’ tests what the code DOES
                              (bugs included, happily asserted)
  test written BEFORE code  β†’ tests what the code SHOULD do
                              and proves the test can fail
diagram
WHAT TDD ACTUALLY IMPROVES

  βœ“ interface design     you're the first consumer of your own API
  βœ“ small units          hard-to-test code is usually badly factored
  βœ“ refactoring nerve    green suite = permission to change things
  βœ— not a substitute for integration or E2E coverage
  βœ— not free β€” expect it to feel slower for the first week

How it works

  1. Write one failing test naming the behaviour you want. Run it and watch it fail.
  2. Write the minimum code to pass β€” hardcode if that's genuinely minimal.
  3. Add the next case; the hardcoding stops working and forces the real implementation.
  4. Refactor with the suite green. Behaviour must not change in this step.
  5. Repeat in short laps. If a lap takes 20 minutes, the step was too big.

Trade-offs

TDD fitsTDD fights you
Pure logic, hooks, reducers, parsersExploratory UI and visual design
Bug fixes (reproduce first, then fix)Spikes and throwaway prototypes
Well-understood requirementsRequirements you're still discovering

The honest middle ground most teams land on: TDD for logic and bug fixes, test-after for UI composition, and always write the failing reproduction before fixing a reported bug β€” that one habit is non-negotiable and pays for itself immediately.

Interview angle

"Do you practise TDD?"

  • For logic-heavy code and for every bug fix, yes β€” a bug without a failing test first has no proof it's fixed.
  • For visual and exploratory UI work I build first and test the settled behaviour, because the interface is still moving.
  • The durable benefit isn't coverage, it's that untestable code is usually badly designed code, and TDD surfaces that immediately.

Recap

  • Red, green, refactor β€” and the red step is what proves the test works.
  • TDD is an interface design tool that produces tests as a by-product.
  • Reproduce every bug with a failing test before you fix it.