With testing code, there are competing approaches of outside-in vs. inside-out.

Instead, I work outside-in *then* inside-out:

Outside-in means writing high-level tests about the expected functionality, then testing and extracting smaller and smaller pieces of functionality.

Inside-out means testing and writing the smaller pieces of functionality and composing them into larger functionality.

(1/3)

Instead, I start with top-level functionality and write tests for what the final expected output/behavior is (outside-in). These tests will fail.

To get these tests to pass, I descend down, writing failing tests for simpler and simpler pieces of functionality.

(2/3)

Eventually, I arrive at the lowest level with ridiculously simple utility functions.

I get those low-level tests passing, then climb back up (inside-out).

I go up a level, use my new functions, get tests passing, and keep climbing until my top-level functionality is done.

(3/3)