Agile – How to practice ATDD if design is not yet emerged from TDD

acceptance-testingagiledesigntddtesting

Despite being very stakeholders friendly, ATDD aimed to provide a "stop" line when a feature has just been done. This avoids wasting time to add non-focused (and sometimes useless) code.

That's why some teams start by establishing a walking skeleton of the application, and directly specifying with an acceptance test the first required feature.

Let's suppose this first acceptance test (not representing a relevant first acceptance test, just being an example):

Given Michael has just been created in the application,
his status should be left to non-activated.

I want to write my acceptances tests focusing on business logic directly (use-cases), not dealing with GUI for business rules.

Thus my question would be…how to write it? since I don't even already know what is a "User", what is a status etc…
Indeed, shouldn't it be the role of TDD to emerge the design and therefore these components?

But if I firstly practice TDD in order to emerge them, the benefit of ATDD (as a stop line) would disappear.

I imagine that it would be more consistent to write some acceptance tests (before entering TDD cycle) when the project has well progressed, since all main components would already be designed.

To sum up, should I always write my acceptances test BEFORE my TDD cycle?

Best Answer

Acceptance tests access the application through a special purpose API.

You presented this use case:

Given Michael has just been created in the application, his status should be left to non-activated.

The API implied from this use case is something like:

CreateUser(String name);
enum UserStatus {non-activated};
UserStatus GetUserStatus(String name);

So far this has nothing to do with TDD. It's just a simple API that your acceptance tests can use to access the application.

Now, to make this acceptance test pass, you'll have to implement this API. That's when you start doing TDD. The decisions you make while test-driving the solution will help you determine the design of the application.

Note that the design of the application has nothing to do with the design of the API that's used by your acceptance tests. That API is an adapter layer between those tests and your application. That layer allows your application to assume any design you so desire.


Regarding TDD and design. It is true that design emerges from TDD. But TDD is not the sole process by which you design your application. You also think through the design in many other ways. You might draw some UML diagrams. You might use CRC cards. You might have a design session with your co-workers. Indeed, you should likely do ALL of these things.

And you should also allow designs to emerge with TDD. TDD doesn't replace previous design tools, it adds a new tool to the kit.

Some folks will likely complain that this sounds like BDUF, and doesn't sound very "Agile". The problem with that is the letter 'B'. It's entirely true that we don't want to do BIG design up front. But it's not true at all that we don't want to do some design up front. We do! A few hours, or even days of design up front is not bad. Months and months of it is.

Related Topic