Jens Schauder is software developer since 1997. He loves software development for the constant challenges and constantly changing environment. A great chance to learn and teach. He is also blogger, author of various articles and speaker at conferences. Jens is a DZone MVB and is not an employee of DZone and has posted 86 posts at DZone. You can read more from them at their website. View Full User Profile

Sketch and Test

12.22.2011
| 2789 views |
  • submit to reddit

I try to do TDD as much as I can. But sometimes (for example last Friday) I don’t know how to get started. This happens when I don’t have a plan of how the code should look in the end, possibly because don’t completely understand part of the problem. Especially I didn’t know how I would be able to test it, due to the fact it the code had to interact with a different system and a database.

The pragmatic programmer recommends a tracer bullet or spike in this case. This means you implement some kind of prototype in order to clarify how to implement it properly.

And than you throw that away and implement it properly again, which for me means test driven.

Do you really do that? For me this goes against the principle of baby steps and of refactoring instead of rewriting code.

Also I was fearing it wouldn’t help much, because the problem wasn’t so much that I was unclear about the code, but about how to test it.

So last Friday I tried a different approach. I call it ‘Sketch and Test’

I started by implementing the complete thing in one single class. Without tests (scary, I know). But I never actually executed the code. I just wrote it as I thought it should work.

Once this sketch was finished I looked at the code and considered the changes I needed to make in order to test it.

I did the changes and finally created the tests, fixing the bugs I found in the progress.

Only when all the tests where in place and green I actually started the application and tested the new feature.

It worked, i.e. the feature did what I expected. The code qualifies as clean and I had complete code coverage with the only exception of some weird exception handling code, that I found hard to trigger in tests.

What do you think? Is this a viable approach? Or is it just a symptom of my limited TDD skills? Or both?

 

From http://blog.schauderhaft.de/2011/12/18/sketch-and-test/

Published at DZone with permission of Jens Schauder, author and DZone MVB.

(Note: Opinions expressed in this article and its replies are the opinions of their respective authors and not those of DZone, Inc.)

Tags:

Comments

Mladen Girazovski replied on Thu, 2011/12/22 - 3:03am

Hi,

I try to do TDD as much as I can. But sometimes (for example last Friday) I don’t know how to get started. This happens when I don’t have a plan of how the code should look in the end, possibly because don’t completely understand part of the problem. Especially I didn’t know how I would be able to test it, due to the fact it the code had to interact with a different system and a database.

 use mocks, and use them to mock roles.

When TDD, you don't write integration tests, you write isolated unit tests, so you need some some kind of mock or stubbing approach.

And than you throw that away and implement it properly again, which for me means test driven.

That is not test driven.

With TDD you don't have prototypes that you throw away and rewrite from scratch.

You might have a fake implementation of a method and mocks of interfaces, you will have to (micro-) refactor constantly, but you do not throw away the code that you have and rewrite it from scratch, instead you'll use babysteps to transform the code you have into the code you want to have.

In the beginnning if found TDD hard, not because it is hard, but because old habits die hard, as a expirienced developer the biggest obstacle in learning TDD is yourself, your habbits, how you are used to writing code.

When you don't know how to start, start simple, i usually tend to write my first test on a new class for the constructor, starting with the no argument constructor, which will be changed during the writing of the test and prod code.

Also, i find using a DI  framework like Guice or Spring makes it much easier to write testable code, so IME it is an advantage to use DI when TDD.

Roger Lindsjö replied on Thu, 2011/12/22 - 3:31am

What I usually do is to isolate the code in the test and then later push it down into a class (or possibly multiple classes).

I almost always know what to test for in the next step as I don't randomly push puttons on the keyboard (well, on a bad day it might feel as if I do), so the next step will be "pass use object to validator" or "calculate force between two particles" or "invalid date gives error", and I know how to start a test for that. However, a moment later that test might be broken or invalidated because my understanding of the problem has increased and the code did not longer need a user ar should not calculate the force between particles. Now the decission comes to either rework the test if it is a valid test which happens to be broken or remove it if it is no longer a valid test.

I hardly ever know what my final code will look like, so during the process a lot of tests will be written that later gets removed. For me that is just part of how the code evolves. 

Jens Schauder replied on Thu, 2011/12/22 - 6:07am in response to: Mladen Girazovski

Hi Mladen,

Mocks didn't help in that case, because I wasn't clear how the interaction was going to work. Therefore I wasn't clear what to mock. 

Also while prototyping and spiking isn't necessarily part of TDD it is a popular and valuable  technique when facing a lack of understanding with the coding challange at hand.

 DI is an important pattern, DI frameworks not so much IMHO, but thats a topic for an article on its own.In anyway in this case the 'other system' was a database so DI didn't help that much.

Jens Schauder replied on Thu, 2011/12/22 - 6:10am in response to: Roger Lindsjö

Hi Roger,

I agree, most of the time I know the next thing to test or next 5 things to test. But I do know the structure of my code. Not every detail, but the rough structure.

 But then there are the cases where I don't know either ...

Mladen Girazovski replied on Thu, 2011/12/22 - 6:46am in response to: Jens Schauder

Mocks didn't help in that case, because I wasn't clear how the interaction was going to work. Therefore I wasn't clear what to mock. 

 Well, TDD will help to define the interaction if applied properly, its part of the so called "interface discovery", where collaboraters and their interfaces are "discovered" while writing the test code. "interface discovery" is what makes TDD a design tool.

 Also while prototyping and spiking isn't necessarily part of TDD it is a popular and valuable  technique when facing a lack of understanding with the coding challange at hand.

 Of course, one way or another, you will need to know out what is happening in APIs/frameworks/libraries that you use.

You could write "throw away code" (aka "Prototypes") for that, or automated unit tests, the advantage of the latter is that you can keep your tests, either as documentation, or as a test suite that will ensure that future version of the lib still work as expected, those kinds of unit tests are sometimes called "learning tests".

 

 DI is an important pattern, DI frameworks not so much IMHO, but thats a topic for an article on its own.

Maybe my last statement wasn't clear enough, without Di, i think TDD is way more complicated than without, so for me those two go together, Since DI is something completely normal for the job today (and most likely used anyways) i don't think it adds additional complexity when learning TDD.

 In anyway in this case the 'other system' was a database so DI didn't help that much.

 I don't understand that statement, but i probably misunderstood you.

If you use DAOs/Repositories for encapsulating DB Access/Persistence, the classes that use them (Services or even Domain Objects in DDD) need access to them, this is where DI comes into play. Mocking a DAO/Repository is usually a text book example for mocking, because it shows all the advantages of mocking (faster, no real DB needed, simplier to setup for a test, more controlable since there is no network or other external system involved, etc. pp.).

 

Not sure if i got you right, but it seems that you are trying to apply TDD to a system that already exists?

Loren Kratzke replied on Thu, 2011/12/22 - 11:16pm

I would like to approach this from a different direction and defend sketching (sans unit tests) - heresy around here, I realize that.

There is no shame in writing code that you may or may not throw away, as long as you learned something in the process.

It helps me to think in the deep and abstract when I lay out some packages and interfaces in my IDE. And I may even need to write some code just to learn how to use a 3rd party lib. I do not feel compelled in the least to actually write tests in order to analyze, think, or learn.

Imagination and curiousity are gifts. Time is precious. Remember, it is only TDD. Just a methodological tool. Even TDD has its boundaries of usefulness.

In my experience, that which does not have boundaries can be only classified as either bullshit or stupidity. Word to the wise.

 

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.