Test Driven Development (TDD) and Moving Forward with Less Technical Debt

Note: This is a work in progress, not gospel. So know that it will most likely change over time.

Overview

 

Before we get into TDD and how it will eventually make our lives easier once we adjust to using it, I want to go over a bit of what we do now.

 

Right now we use the traditional waterfall type of pattern...

 

DesignImplementTest.png

 

And this works, but all too often we skip the last step because we're out of time or have to fix something someone else found. Testing shouldn't be a skippable step, but it ends up that way far too often.

By pushing tests to the end of the process and then not getting them done, we end up with painful test cycles with QA and the field as we've been doing the last few releases. As a result, we end up with a pile of technical debt - bugs start to pile up as QA reports them, incompatibilities with previous releases creep in,and so on...

 

Test Driven Development (TDD)

 

Instead, we should be using the TDD model, which changes the pattern a bit...

 

TDD1.png

By building the tests into the pattern earlier, we should reduce the frequency of having to go back in and fix bugs later because we're testing as we go and creating more stable code all the way along.

How this works is something like this (for new features):

 

   1) Design: Figure out what you want to do
   2) Test: Write a test to express the design
      * IT SHOULD FAIL
   3) Implement: Write the code
   4) Test again
      * IT SHOULD PASS

 

For bug fixes, it's a little different:

    1) Get some sample code (that breaks)
    2) Turn it into a test
       * IT SHOULD FAIL
    3) Fix the bug
    4) Test again
       * IT SHOULD PASS

These patterns should be used for all bug fixes and new features we implement from now on. And it's not going to be easy to get used to this model for some of us, but it will get easier with time and practice.

Hopefully by writing more of this type of focused unit test, we:

    * Write tests once
    * Keep them somewhere sensible (like a separate plug-in with the name ".test" appended to the end)
    * Run frequently (one click) as a developer and run tests as part of every build
    * Don't require human input (which makes tests faster)
    * And we provide machine-parsable output like JUnit logs that say whether a test passed/failed

 

The benefits are many, but they boil down to two main ones:

 

   * We get tests as part of the process, rather than an afterthought.
   * We get more stable code.

 

Moving Forward...

 

Now how are we going to do this in Eclipse?

 

Well, we're going to use JUnit or testNG (until a decision is made, focus on JUnit) as much as possible to test the underlying code. The tests should be specific to a particular problem and run quickly. Use mock objects where possible to mock up whatever you need, reducing the runtime dependencies.

 

It's been suggested that we use Mockito, JMock, or testNG + PowerMock to handle testing with mock objects.

 

Once we've tested as much as we can of the frameworks, APIs, and underlying code with JUnit, we should look at building a suite of SWTBot tests.

The SWTBot tests should not only test individual bits of functionality, such as clicking this button should generate this result, but should also start focusing on specific use cases and doing more end to end testing. These two types of tests should be kept separate.

So we're looking at three types of tests:

    * JUnit Tests and Test Suites
    * SWTBot functional tests
    * SWTBot integration tests

The first two types of tests should be run as a regular part of the nightly builds. And the integration tests should probably be run weekly as part of the weekly integration builds to make sure nothing was broken.

 

Interesting Testing Resources for Reading...

 

 

Additional Resources