We’ve all been there. You’re working on a "disruptive" project, the kind where the requirements are shifting like sand and the architecture is a giant question mark. You want to follow TDD (Test-Driven Development), but you’re staring at a blank screen because you have no idea how to Arrange the test.
How can you set up the dependencies, mock the database, or initialize the state when you don't even know what the "state" looks like yet?
Most devs give up here. They "code it out first" and promised to add tests later (spoiler: they don't). But there’s a better way to handle the chaos. If you don't know where to start, you’re likely following the Arrange-Act-Assert pattern in the wrong order.
To survive disruptive development, you need to flip the script. You need to start with the Assert.
TDD is an Executable Specification, Not a Test
Before we dive into the "how," let's fix our mindset.
A TDD test isn't a post-mortem checkup; it’s an executable specification of two things:
- The outcome: What should actually happen?
- The interface: How do we tell the code to make it happen?
In a disruptive product, the "how" (the Arrange) is a mystery, but the "what" (the Assert) is usually the only thing you actually know. If you didn't know the desired outcome, you wouldn't be writing the code in the first place.
Step 1: Write the Assert First (The Destination)
Start at the finish line. What is the one thing that must be true after this code runs?
- Does the user get a "Success" message?
- Does the price calculation equal $99.99?
- Is the new record present in the list?
Decide how that outcome should be collected and write that line of code. It will red-squiggle. Your IDE will complain. That’s good. You’ve just defined your goal.
The Golden Rule: The assertion is the reason the code exists. Without a clear assertion, you aren't writing a feature; you're just typing.
Step 2: Write the Act (The Doorbell)
Now that you know the destination, how do you get there? This is where you design your API.
The Act is the trigger. Decide how you want to call this functionality. Should it be a method call? An event trigger? What parameters does it need to know right now to do its job?
By writing the Act after the Assert, you’re forced to design a clean interface that serves the outcome, rather than an interface that is limited by whatever junk you have in your "Arrange" setup.
Step 3: Write the Arrange (The Plumbing)
Only now, once the Assert and Act are staring you in the face, do you tackle the Arrange.
By this point, the "loose ends" are obvious. Your Act step likely requires an object that hasn't been initialized yet. Your Assert step likely checks a value that needs to be seeded. The "Arrange" step essentially writes itself because it’s just filling in the blanks required by the previous two steps.
Leverage the "Red-Squiggle" Workflow
One of the most powerful ways to do this is to lean on your IDE’s autocomplete.
- Write the Assert using a class or method that doesn't exist yet.
- Write the Act to call that non-existent method.
- Use your IDE (Alt+Enter or Cmd+.) to "Generate Class" or "Generate Method."
This creates a "skeleton" of your production code. Now, you aren't guessing what to write; you’re simply filling in the blanks of a skeleton that you’ve already proven is exactly what your test (the spec) needs.
TDD as a Debugging Tool
In disruptive development, the biggest hurdle is cognitive load. Trying to figure out the setup, the logic, and the outcome all at once is a recipe for burnout.
By flipping the order to Assert -> Act -> Arrange, you break the problem into three tiny, manageable decisions. You’re no longer "testing"—you’re documenting your intent and letting the test guide your hand.
The best part? When you finally sit down to write the actual logic, you already have a working test and a debugger ready to help you evaluate your attempts in real-time. That’s not just "clean code"; that’s a professional safety net.
