I've heard about TDD more than one year ago, but until now I didn't manage to get myself started with it. Indeed, one of my greatest doubts is always what to test. The examples given always shows test to verify if some business rule is being correctly implemented.

So, for instance, in an auction software we have the business rule "an user can only post a bid on a item if the value is greater than the value of the last bid". That is fine, this kind of thing is easy to imagine we need to ensure to be working. Those are things the end user of the system would care.

But sometimes we are working on the infrastructure of the system. Authentication and authorization, selection of resources for users, security verifications and so on. On these cases it doesn't seems obvious at first what should we test.

So, currently I'm not yet using TDD because always when I think to do so I find myself questioning "ok, now what tests should I write" and I never now to answer this question. How can I know which tests I should write when starting to build an app?

2 Answers
2

Look, your software has to do something or else you wouldn't be writing it. "I need something to verify people's credentials." Is a perfectly fine high level requirement to start making tests from.

TDD is at its core a framework for you to ask "what is this thing going to do?". You want to authenticate and authorize users? Great. Now write your ideal code that authenticates and authorizes users (in the form of a test). This gets you to actually define what your code needs to do, as well as a nice interface for someone to use it (since you started by using it). Making the actual working code to fill in the gaps comes last because for almost all code, the interface matters more than the implementation.

What to test is simply what you're trying to implement rather than how you mean to implement it. If you don't even know what you're trying to accomplish, then maybe you should stop writing code and go figure that out first.

The reason I think you have asked a great question here is that you really pinpointed the major impediment to delving into TDD--what do you test next? Answering that question is much easier with just a few notions clear in your head.

(1) TDD, contrary to the name, is not about testing.

“Folks who do TDD for a while typically come to the conclusion that
the only thing that TDD has to do with testing is the appearance of
the word test in its name. That’s a bit of an exaggeration, but it’s a
common one used by TDD’ers to help clarify the issue. We use unit
testing frameworks to do TDD, and we write the example code in methods
that can be executed by the test runners that come with unit testing
frameworks, but that’s about the end of the commonalities between TDD
and testing.”
― Scott Bellware, Behavior-Driven Development

(2) The goal of TDD is not to come up with tests; it is to come up with specifications (or behaviors).

“The entities we write are not actually tests. They are
specifications. What we are doing is replacing traditional specs with
automated specs. The process of writing the specification is an
analysis task, one that leaves behind a suite of tests as a
side-effect artifact...” ― Scott Bain, Overcoming Impediments to
TDD

(3) To determine what to test next (or even where to start) the question then simplifies to: What is the next most important thing the system does not yet do?
(Let me touch explcitly upon a point implicit in Telastyn's answer: your question suggests you are trying to align unit tests with user stories, but they exist at different levels in the architectural hierarchy. Unit tests--the byproduct of TDD--are much closer to the implementation, much more fine-grained.) So the "next most important thing" refers to implementable thing, not user-story-level thing.

(4) The answer to the question in (3) should be some behavior B. Write that behavior B as a sentence S0. If the sentence is too long or convoluted split it up into multiple sentences S0, S1, S2 ...

Each such sentence Sn names one test.

So with these simple ideas in mind, not only can you figure out what to test, you also come away with the test method name... leaving you with "just" the implementation left to do.