TDD Vs Test Last Approach

You might also like

Download as pdf or txt
Download as pdf or txt
You are on page 1of 4

Today, I’d like to address the topic of when to write tests: before the production code or after.

1. Test-last approach
The test-last approach is the regular approach most of us adhere to, and it’s also the most
intuitive way to write tests.

Basically, you write the application code first and then cover it with tests. Nothing too
complicated here; this is the "normal" way to develop software.

2. Test-first approach
The test-first approach is the opposite: you first write a test for the functionality you are about
to develop and then write the functionality itself.

This is the Test-Driven Development (TDD) in a nutshell. There’s more to TDD than just that
(see below), but the ordering of the test and production code is the most important difference
from the conventional approach.

Here’s the TDD process on a diagram:


● Write a failing test — First, you outline the requirements for the
soon-to-be-developed functionality and express them as assertions in the test.

● Make sure the test fails for a good reason — Next, you need to make sure the
test fails because the requirements aren’t yet implemented. Developers often skip
this step, but it’s a crucial one. The test must fail due to issues with the functionality
under test, not some unrelated issue like an application-wide exception.

● Make the test pass — At this step, you are implementing the actual functionality the
test covers. At this point, the quality of the code is not important; the goal is to make
the test turn green.

● Refactor — If the code from the previous step turned out messy, clean it up. The
reason for separating this step from the previous one is that it’s easier to refactor
existing messy code than to write clean code from the get-go.

3. Test-first vs test-last
Believe it or not, both test-first and test-last approaches have their benefits and drawbacks.
Let’s discuss the benefits of each and then let’s see how you can use both approaches to
the maximum advantage.

3.1. Benefits of TDD


So, what’s the point of TDD? Why would you come up with such a complicated process?

When writing tests, you are constantly dealing with the problem that’s best described as:

Who judges the judge?

Your tests verify the application code, but who verifies the tests? How can you make sure
your tests check the underlying functionality, and not just sit around doing nothing?

This is the problem TDD solves.

By seeing the test fail because of the lack of underlying functionality (or because it’s
implemented incorrectly), you validate that test. You know that, should the application code
stop working properly, the test will point that out.

In other words, this practice reduces the chance of false negatives (false passes): you
already saw the test failing and can expect it to do that again.

This is why step 2 (making sure the test fails for a good reason) is so important. If the test
fails for an unrelated reason (say, the arrange part is set up incorrectly), you aren’t validating
that test and can’t know if it will fail should the underlying functionality break.
With the test-last approach, you have to do this validation manually: change the application
code to simulate a bug, make sure the test fails, and then change the application code back
again. This is tiresome and a lot of people just skip it, which may result in incorrect tests.

TDD is great because this step of validating your tests is baked in to the code-writing
process itself, you don’t have to do any extra work.

3.2. Benefits of the test-last approach


So, what are the benefits of writing the application code first, then?

It’s flexibility.

Since you don’t have to worry about tests, you can easily change your application code:
refactor or even completely redesign it.

With tests, it’s harder to make such a move because you’d have fix those tests after each
redesign.

3.3. When to use each approach


Both approaches have their merits and you should apply each of them at the right stage of
your project.

Those stages can be divided into 2 categories:

● Doing the right thing

● Doing the thing right

Meaning, you first need to outline the scope of the project, to make sure it’s the right
solution, and only then build that solution.

The first stage involves experimenting, sketching your domain model, whiteboard sessions,
etc. You don’t need tests at this stage: they will only drag you down and there’s a good
chance you’d have to throw them away along with the code you are experimenting with.

Once (after enough iterations) you are sure you are doing the right thing, you can proceed to
step 2: doing that thing right. That’s where you can follow TDD and get all the long-term
benefits, such as good test coverage and quality tests.

The problem with TDD is that, in order to be productive, you need to know exactly what you
are building. However, once you do know that, you can benefit a great deal from the test-first
approach.

Another area where TDD shines is bug-fixing. If you find a bug, don’t just fix it right away.
First, write a test to reproduce that bug, make sure it fails, and then fix it. This way, you’ll
never need to worry about that bug again.
--Vlad

https://enterprisecraftsmanship.com

You might also like