Test-Driven Development

Josh McKinzie Dev Methodologies, Technology Snapshot, Testing 3 Comments

We all will agree that having good tests to exercise and validate a developer’s code is a good thing. Unfortunately, so often, writing unit tests is the last thing developers have time for, if they get the opportunity to write them at all.

An example that developers can find themselves in: a development cycle or iteration is drawing near to delivery and the time and effort that was planned for testing to validate the code is spent still trying to “get the code to work” or making fixes to bugs that a few hasty tests drew out. This is not an ideal situation.

Test-driven Development (TDD) turns this situation on its head. Write the tests first then develop the solution. Write tests that demand a solution(s) that meets the business’ needs. Develop the code to pass the tests and you have found the solution. While on the surface this may seem straight forward and simple, but outside the theory, where the rubber meets the road… not so much. There are many situations that make this approach difficult; a few things come to mind like user interfaces or data conditional logic that is not available during unit test runs, not to mention the fact that developers despise writing unit tests. While TDD may not be beneficial in every scenario, we shouldn’t throw the good out with the bad.

What are some benefits that writing the tests first and then coding to the tests provide? Why would I ‘waste’ my valuable development time writing tests upfront?

Several benefits that I have reaped from having tests drive my coding:

Articulating the business needs in code.
Just as development patterns use interfaces and abstract classes to define and structure coding contracts, writing tests before writing functional code helps define a developer’s contract of what that method/class/factory/etc. is intended to produce. These tests help flesh out the design. The sooner that ‘contract’ is in the code, the less likely the developer’s time is wasted redoing and re-redoing code due to the losing sight of the goal.

Less time spent arriving at a solution.
More is less. The sooner a developer knows a piece of code is working incorrectly than the faster and easier it is to fix. The sooner a developer knows that the new code written has just broken existing code the quicker a resolutions can be found. With writing tests first the developer knows when the solutions has passed muster and will continue until it has reached that point. The tests serve as a better reminder of unfinished code than some TODO or FIXME.

Better code quality.
As a general rule: the more weight toward quality than quantity, tests exercising a piece of code, than the fewer defects it will have. While writing the same tests before or after the implementation may not affect the quality of the test, it guarantees that the tests get written.

These are just a few examples of how writing tests up front can benefit the development process. These are not meant to be a comprehensive list, but these have been the key benefits that I have seen from writing tests to drive my development of the solution.

So you say, “That’s great Josh, but we can’t do that because of XYZ.” While TDD can be difficult in different applications or layers of code (think UI), there are many tools that can drastically help. Selenium can help create UI testing. Mockito can help mock in data dependences. JUnit and TestNG are also great unit test frameworks. Using continuous integration systems, like Hudson, to run and report on the status of an application’s tests will provide updates to the progress of development. All of these tools and frameworks add power and easy of use to testing.

There are many implementations of Test-driven Development. If you haven’t read Kent Beck’s book Test Driven Development: By Example or Ken Pugh’s Lean-Agile Acceptance Test-Driven Development: Better Software Through Collaboration, I would strongly encourage you to do so. These two books (especially Beck’s book) have been very helpful to me and will provide more breath and depth to having tests drive development.

Remember that testing code is still only worth the effort you put into it. Sloppy, limited, and incorrect tests will produce less than desirable results. This goes for whether or not the tests are written before or after development.

In summary, I don’t have a silver bullet to get every project done on time, under budget, and be a complete joy to work on, but I do believe that developing tests first and being proactive in the health of the code that you are developing will bring better quality, more available development time, and more satisfaction due to fixing less defects. I hope this post has been beneficial and will prick your interest enough to do some digging into Test-driven Development.

— Josh McKinzie, asktheteam@keyholesoftware.com

About the Author
Josh McKinzie

Josh McKinzie

Share this Post

Comments 3

  1. Phil

    Good article!

    Another benefit that kind of dovetails with your second one is that you end up writing less code. Instead of writing a ton of code that you think you might need, you only write the code that satisfies the test.

    I’ve also found this helps developers break problems into smaller pieces and focus on a piece rather than trying to solve the world’s problems when they code. “Where is this data going to come from? How is this going to be formatted?” You don’t get all bogged down in those questions when you’re trying to satisfy one, specific test.

    Yet another benefit is that writing your tests first virtually forces you to write decoupled code. If you don’t know where X is coming from, you have to stub out some kind of provider for X that you can mock up.

    1. Josh McKinzie

      Thanks Phil.

      Your points are very valid and I have seen the same things happen from my experiences as well.

      It really does help developers break code up into smaller logic parts, sometimes this is just because it is easier to write a test or two for this one known piece while waiting on requirements in the next iteration. This approach can breed more modular code which in turn aids reuse which in turn saves time and errors.

  2. djkieras

    I enjoyed the article, Josh. Unit testing unfortunately tends to be the first thing cut from any project where time is a premium because it often is not well understood. However, it never is too late to add TDD down the road when you can make a more obvious case for its efficacy, show that it would reduce cycles, and get cross-team buy-in.

    For example:

    I worked on building a new system where my team’s product interfaced with another team’s product (also under development) and a database schema with metadata supplied by a THIRD team. As such, whenever there was an error in testing, it became a blame-game as to whose product caused the issue. At that point we had to have the testers work with us to re-create the scenario, capture additional information, then send it on to the teams for analysis. This took a lot of time not only for development, but for the testers to go through all 60+ of their scenarios each time we deployed a test candidate where we “guessed” our code would be working properly together.

    Our solution was to get the testers to create scenarios for us with the appropriate data. This allowed us to mock the data for each scenario EXACTLY as the testing team was ultimately doing with their manual testing, and test behavior against both the database and the products being developed. Additionally, we could run all 60+ of these scenarios using TestNG in just a few minutes, which saved the testers a LOT of time and ensured that the product met their requirements before we deployed it for testing. And each test, if failed, would write out specific debugging information useful for each team so that it would not need to be re-created for analysis…which saved both development teams a lot of time.

    So even though unit testing and TDD was initially not very broad early in the process, it was introduced later in the process when it became obvious it was the _only_ way to get things done on time!

Leave a Reply