Tutorial :How much unit-testing before start coding a method/class?



Question:

I´m starting (trying at least) to do coding using TDD principles and I have this question: how much tests do I need to write before actually start coding?

Take for example a hypothetically Math class and a method Divide(int a, int b).

a) Do I have to fully test all methods of Math class (Sum, Average, ...) before start coding Math?

b) Do I have to fully test the Divide method, asserting for example for division by zero, before start coding the method?

c) Or I can create a simple test assertion and verify that it fails, write the code and check that it´s OK, reapeating the process for each of the assertions of a method?

I think the option c) is the correct, but I couldn´t find an answer to it (I did some searchs but couldn´t find a definitive answer).


Solution:1

Your option c represents fully by the book TDD.

You write one failing test exercising a feature of the class that you are working on and then write only enough code to make that test pass. Then you do this again, for the next test.

By doing it this way you should then see each new piece of code you write being very focused upon a particular use-case/test and also find that your tests remain distinct in what they cover.

You want to end up working in a red-green-refactor fashion, so that periodically you go back over both your code and your tests for places where you can refactor things into a better design.

Of course, in the real world you may end up writing many red tests, or writing more code than a particular test requires, or even writing code without tests, but that is moving away from TDD and should only be done with caution.

The wikipedia article on this is actually quite good. http://en.wikipedia.org/wiki/Test-driven_development


Solution:2

The first thing you want to do is write a specification for each method you want to implement. In your specification, you need to address as many corner cases as you care about, and define the behavior your method should result in when executing those cases.

Once your specification is complete, you design tests for every part of your specification ensuring that each test is not passing or failing due to corner case conditions. At this point you are ready to code up your function implementation and tests. Once this is complete, you refine your specification/tests/implementation as necessary until the results are exactly what you desire from your implementation.

Then you document everything (particularly your reasoning for handling corner cases).


Solution:3

Like others have mentioned, your option c would be the pure TDD way to do this. The idea is to build your code up in small red-green-refactor increments. A good simple example of this is Robert Martin's Bowling Kata.


Solution:4

Well You can probably write

@Test  public void testDivide() {     Math math = new Math();     int result = math.divide(20,2);     Assert.assertNotNull(result);  }  

That's it, now when you run this your test will fail so you fix your Math.divide method. and add cases in the next step

this is a very ideal way but everyone knows it's not always this way.


Solution:5

The definition of "unit" is not universal, sometimes the unit is the class, sometimes it can be a method. So there is no real universal answer.

In this particular case, I would consider the unit to be a method so wouldn't not all methods before to start coding. Instead, I would do things incrementally, methods after methods. This eliminates a).

However, when writing a test for a method, I would write a rigorous test i.e. I would test the passing and the non passing cases, test at the limits, test the special values, etc. When writing a test, you're defining a contract and this contract should include exceptional situation. Thinking of them from the start do help. And for me, the point of having a green light is to be done so I want my test to be exhaustive. And I think that this is b).

If your test is not exhaustive, then you're actually not done with your unit even if the test is passing and I don't really see the point. I guess that this is c).

So my choice would be b).


Solution:6

If you are going for completeness you should design and code your unit tests prior to development and then develop the primary functionality to the created unit tests. The more thorough you are the clearer the scope and better the final quality. If time and functionality allow, I would create tests for each method/function.


Note:If u also have question or solution just comment us below or mail us on toontricks1994@gmail.com
Previous
Next Post »