Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Discovering other objects while doing TDD

Tags:

tdd

testing

I am trying to practice TDD.

My understanding is that TDD should go like this

  1. Write a test list for the interface/class I am going to develop.
  2. Start with the easiest not implemented test from my test list.
  3. Write the test, no implementation code yet.
  4. Write the interface of the class to make the code compile.
  5. Run the test resulting in one failing test.
  6. Write the implementation making the test pass.
  7. Refactor the mess I've made.
  8. Goto 2.

The problem I have is when writing the implementation or doing the refactoring. I often come to the conclusion that the implementation I just wrote should be delegated to another class.

What should a true TDD'r do at this point?

  1. Leave the existing test list alone for a while and create a new one for the newly discovered class (the same problem can manifest itself when implementing the new class offcourse)
  2. Go the Interaction Based way of testing and Mock the new class, continue with the testcases of the class you are working on and come back later to create a correct implementation of the mocked class.
  3. This situation should not present itself. I probably have not thought out my initial design well enough. (but wouldn't that defeat one of the purposes of TDD?!).

I'd love to know how other people handle these situations.

like image 335
Lieven Keersmaekers Avatar asked Jun 19 '09 13:06

Lieven Keersmaekers


People also ask

What is not true about well written code using TDD?

Many programmers have tried this technique, failed, and concluded that TDD is not worth the effort it requires. Some programmers think that, in theory, it is a good practice, but that there is never enough time to really use TDD. And others think that it is basically a waste of time.

What is main focus of TDD?

Test-driven development (TDD) is a software development process relying on software requirements being converted to test cases before software is fully developed, and tracking all software development by repeatedly testing the software against all test cases.

Which type's of tests do you typically write when doing test driven development?

With developer TDD you write a single developer test, sometimes inaccurately referred to as a unit test, and then just enough production code to fulfill that test. The goal of developer TDD is to specify a detailed, executable design for your solution on a JIT basis. Developer TDD is often simply called TDD.


2 Answers

Don't look for a one-to-one relationship between your tests and your classes. If you decide to introduce a new class, let that be a refactoring supported by the original test, and add tests in the appropriate place (where that is depends on the specific case) when you want to add functionality (or to test eventualities you need to cover that you didn't test for yet).

I would add that the main success in TDD is to get into the rhythm of red-green-refactor. When you feel the benefit of that rhythm, you have started to "get" it. That isn't to say you will find it worthwhile in all cases, but until you feel that rhythm you haven't gotten to what its advocates like about it.

And there is usually (especially in architecturally complicated applications, like n-tier applications) some amount of up-front design. Nothing sketched in stone, but enough to give the units a place to go. Of course the architecture may evolve in an agile methodology, but a general idea of the landscape needs to be there if there are multiple layers to the architecture.

EDIT: (In response to the comment). Should the new class get tested in its own right? Not necessarily. It depends if the class develops an importance of its own. When you are unit testing, you are testing a piece of functionality. It isn't an integration test just because there are two classes involved. It becomes an integration test when two units start interacting. The boundary I typically think of is if I have to set up significant state in group-of-classes A to interact with group-of-classes B, and especially if group-of-classes A calls group-of-classes B and what I am interested in testing is how B reacted to A, then I'm looking at an integration test.

like image 158
Yishai Avatar answered Sep 20 '22 17:09

Yishai


The problem I have is that when I arrive at point 6 & 7, at some point in time I invariably come to the conclusion that the implementation I just wrote should be delegated to another class.

Realizing your design would be better with a different class - that's design, and that's the point of TDD. So it's a fine thing, and it shouldn't bother you.

But it's bothering you. So what to do? Recognize that delegating to another class is a refactoring; this is something to be done after step 6, during step 7. Once you're green, refactor to a better design. You've already got the tests for the new class; they're just wired to call the original class. That's perfectly fine. After extracting the class and delegating, if you would be more comfortable having the tests call the extracted class directly: go for it. No harm. If the extracted class starts to get used by other callers, I'd recommend it, and maybe when you start calling it from other classes is a good time to do that (but if it bugs you now, do it now).

like image 25
Carl Manaster Avatar answered Sep 18 '22 17:09

Carl Manaster