One of the team, Alex, recently shared a paper that compares quantitative data from Test Driven Development and Test Last Development. The paper summarised, that there is no evidence supporting the claim that TDD differs from a TLD approach in terms of testing effort, external code quality, and developers’

productivity.

This got me thinking as to what other factors are at play and which method really is best.

At DVELP, we use testing for two primary purposes:

1) Clearly defining the scope of a feature e.g. It should return the sum of the values

2) Verifying our implementation, matches our expectation e.g. 1 + 1 = 2

The latter, predominantly binary in it's output would commonly be referred to as a unit test. The former, significantly broader in interpretation and much more subjective would commonly be known as an integration test.

For those who are un-aware of the principles of TDD and TLD a brief overview;

Test Driven Development (TDD) assumes that tests are written before any of the code itself

Test Last Development (TLD) assumes that the functional code is written first and the tests are layered on afterwards

TDD

Although TDD is designed to be exploratory, those who have tried following it to the letter will likely find it un-necessarily repetitive. Designing an interface is an iterative process, which if abiding by the 'rules' of TDD, will require writing and re-writing specs for each iteration. Yes, this can help improve spec coverage, but it can also be a massive and un-necessary time suck.

With that said, writing the test first does get you to think in more detail about how that interface is going to work, what problems you could face and how to implement the feature in the most efficient manner from the get go. e.g.

Test (rspec):

describe '#sum' do it 'sums the values' do expect ( Calculator . sum ( 1 , 2 )). to eq ( 3 ) end end

Code (ruby):

class Calculator def self . sum ( * values ) values . inject (: + ) end end

TLD

In contrast, TLD assumes you get stuck in right away and once you're done, you write the tests to fit. TLD is much less repetitive and saves you time speccing exploratory steps whilst determining the final interface.

The downside is that the tests are often tightly coupled to implementation. The developer is 'cursed' with the knowledge of internals and might chose to ignore how the method reacts to an unintended input or skip some unlikely corner cases. In theory this can lead to lower quality tests.

Not to mention if you're working in a team environment and you get hit by the number 38, you'll leave your team mates both bereft and puzzled.

Code:

class Calculator def self . sum ( * values ) values . inject (: + ) end end

Test:

describe '#sum' do it 'sums the values' do expect ( Calculator . sum ( 1 , 2 )). to eq ( 3 ) end end

TAD

So if TLD leaves your be-grieved team mates bemused and TDD is rather repetitive and a little time consuming, how about Test Around Development?

Test Around Development is the concept of clearly stating your expectations at the beginning (with the use of pending tests), writing the meat of the code and then filling in the moving parts to finish. e.g.

Pending test:

it 'returns the sum of the values'

Code:

class Calculator def self . sum ( * values ) values . inject (: + ) end end

Completed test:

describe '#sum' do it 'sums the values' do expect ( Calculator . sum ( 1 , 2 )). to eq ( 3 ) end end

With this approach we achieve the following key objectives;

Clearly define the scope and expectation of the feature

Reduce repetition

Reduce the likelihood of blackholes

Improve communication with your #TEAM

Like with all coding practices, the merits and drawbacks are highly subjective and the most important thing to remember is to write those tests, but if you're current flow just isn't working for you, why not give TAD a go!