DevOps Zone is brought to you in partnership with:

Evgeny Goldin works as a Technical Evangelist for the JetBrains TeamCity CI build server. He speaks Java, JavaScript, Perl and Groovy. His favorite products are MediaWiki, Intellij IDEA, Git, Artifactory, Gradle, YouTrack and TeamCity. He enjoys driving, learning and solving challenging problems. He doesn't like wasting time and being unproductive and believes that simplicity, attention to details and tidy working environments are the most efficient approaches to successful delivery. Evgeny is a DZone MVB and is not an employee of DZone and has posted 17 posts at DZone. You can read more from them at their website. View Full User Profile

TDD for unbelievers

06.25.2011
| 8705 views |
  • submit to reddit

I have to admit, I was not-so-good with TDD (Test-driven development). I just didn’t see how it can help me to deliver a better software. Products and solutions I developed were pretty much rock solid and it felt good to see them running for years. What else did I need?

But it was time to give TDD another try. Obviously, it became quite impossible to ignore this subject today, especially when people talk about continuous deployment already!

“Real Developers Don’t Need Unit Tests” (video) does a good job in describing once again what TDD is good for. If you don’t see a value in TDD, like I did – please, do yourself a favor and watch this session.

Some major takeaways:

  • I guess the main point is that TDD is not about writing failing tests first, as I assumed for years. It is a way to design and implement a system, not from one’s head or some silly design specification but from the actual needs. Tests are a pleasant side-effect, but what they really do is actually show how the system works. I think it was “Groovy in Action” that initiated an excellent tradition of using asserts as a way to demonstrate what code does. What describes better the end result?
    assert "test" == str.test()
    // Or
    str.test()  // prints "test"


    It may sound like an obvious thing but making a mental switch from “Tests for the sake of tests” to “Design and implement through tests” was my first enlightenment as I watched the video.

  •  

  • There are three phases in doing TDD: Red, Green, Refactor. First, you provide a demonstration of a new feature. It takes a form of a failing test, right. But it is a demonstration of a new feature nevertheless. Then you implement it. And then you clean up, refactor and tidy up. The cleaning process is a critical one! From my experience it is widely and commonly omitted as people get to the “Green” phase and commit. This is exactly where products start getting a bad smell, clarity get lost, things get messy and next thing you hear is “Do not ever touch it”.
  •  

  • Test behavior, not implementation. Another common belief about unit tests is they should test class methods and state transitions, i.e., current class implementation. The problem with this approach is that tests break each time implementation changes. And instead of updating tests accordingly it is very tempting to comment them out, <exclude> them from running or simply @Ignore. If one tests functionality and behavior then it shouldn’t break! If there’s a need to test a private members then they probably do too much and should be extracted to their own class and their own tests. “Design and implement through tests” again.
  •  

  • When doing code review start from the tests. Since tests are the answer to the question “What this code does?” it makes sense to review them first to concentrate on a meaningful parts instead of everything. Especially when time is tight and only the relevant code should be reviewed.
  •  

  • Unit tests are not a substitution to integration tests, acceptance tests and QA processes. As was mentioned above, TDD doesn’t really serve the purpose of testing although it is called this way. It doesn’t test for real and doesn’t try to find bugs, it only demonstrates application’s ability to do something.
  •  

  • Treat your tests as production code. Tests should not be written as a throw-away code that is never maintained or updated. Tests are application’s user interface, its front page, if you wish. And we wouldn’t like our front page look ugly, would we?

 

Now, what really stops me from doing TDD starting from tomorrow? I would say a lack of commitment of everyone involved. To integrate a real TDD process into organization is very costly. It will take months until all infrastructures are set up and people stop spending a noticeable extra time on writing tests. Initially it creates a huge overhead, especially when dealing with legacy code. Eventually, an extra time spent on writing and maintaining tests pays off by producing a code that is better designed and is of much higher quality. After all, that’s how people get to continuous deployment that I mentioned above – they started with something, right?

Those willing to pay the extra price of doing TDD can get to it. Those running after new features every two weeks will have a harder time, of course.

P.S.
See a follow-up post “JUnit Updates”.

Published at DZone with permission of Evgeny Goldin, 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

Jeff Anderson replied on Sun, 2011/06/26 - 12:23pm

Get into BDD, it's better named for what we are trying to do with TDD IMHO

Kim David Hagedorn replied on Sun, 2011/06/26 - 3:09pm

Am I the only one who feels like BDD is imposing quite a lot of ceremony on developers? Of course, the perspective from which you design features and tests is quite important and you should communicate that to your developers. But all that 'boilerplate' writing in stories and tests feels a bit strange to me.

Nicolas Bousquet replied on Mon, 2011/06/27 - 6:36am

TDD is like a religion. We have fanatics that think if you don't do it your are wrong and will go to hell. I'am not against it (that is people using it), but I think that I should have the choice as a developper to do my test before of after.

Robert Lauer replied on Mon, 2011/06/27 - 6:57am

"Test behavior, not implementation" is easier said than done. However, TDD is a great tutor for it (and personally, I think that TDD serves us best as a learning method, not as a "design" method or test method alone).

Comment viewing options

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