Test Driven Development

Borland Conference 2005

by Charlie Calvert


Index

Initializing class to with interface for six step Noel example.

Overview

 

Some Links to More Articles I've Written on this Subject

 


Part I

Introduction to Unit Testing and TDD


 

The Different Kinds of Tests

There are several different kinds of tests, and the boundaries between them can be quite fuzzy at times. Nevertheless, it is possible to make at least a few generalizations which can help you navigate the lingo found in most texts and web sites.

Unit Tests

Integration Tests

Functional Tests

Stress/Load/Performance Tests

Acceptance Tests

Regression Tests


Unit Testing


Why Use Unit Tests?


Reasons Not to Use Unit Tests

 


 

Part II

Unit Testing Technology and Syntax: NUnit and DUnit


 

Install and Setup

NUnit

DUnit


Getting Started


First Demo: Getting Started with NUnit


NUnit Basics


Second Demo: Getting Started with DUnit


DUnit Basics


DUnit Links to Articles


GUI vs Text Tests


Color Coding


The Config File Issue


NCover


NAnt


 

 

 

Part III

Test Driven Development: Refactoring


Agile and XP


Third Demo


Write Tests First


When to Write Tests


Communication and Change


Caveats


XUnit Family


Red Green Refactor


Checks

Write tests that check for expected failures.


Problems

You should cover all, or nearly all the classes in your program with tests. How are you going to find the time or skill to write all that code?

Many people suggest that you write the test first, and the code second.

Some classes are hard to test.

From the point of view of a Delphi programmer, some forms are going to seem impossible to test.

Finding the answer to these kinds of questions turns out to be a complicated quest.


Architecture Philosophy

Good design

Perhaps the most important thing about Unit Testing is that it encourages good design philosophies.

Transparency

Tests should be simple

Quick

As a rule, tests should run quickly. If you make a change to your code, you should feel free to test right away.

UI Testing?

This is not a strength of unit testing. Refactor your code so it is not necessary.

Loose Coupling

To promote reuse, you want to use interfaces and abstract classes to define a loose relationship between classes.

Refactoring

If you can't see how to easily test your code, it is probably time to refactor. Refactoring is a technique for improving the design of working code.

Small Classes

Create small, easy to use classes. Create small, easy to maintain tests. There is more code in my final example from the Suite program, but it can be called with just two lines of code.

Failure important

"The tests also force programmers to think about the possible ways a program can fail. It may seem obvious, but I have found this to be one of the hardest things to teach."

Not Easy

"Where there is a will, there is a way to test." - Don Wells


Refactoring


Design


Simplicity


 

Patterns

Patterns are a way of preserving programming lore.

Patterns are lists of proven techniques for solving common problems.

You can read more about patterns in this attached article.


UML and Agile Modeling

Modeling techniques can help you discover the best architecture for your program.

For more information on this subject, see the attached article called Introduction to UML with Together and JBuilder.


Getting Stuck

There is going to come a time during development when all of a sudden you are going to say: "Hey, this doesn't work. You can't write tests for the kind of code I want to create." That is natural, but you have to understand that there is still further for you to go. There is more exploration necessary. In fact, there probably is a solution, only it is requires that you start thinking in new ways about how to write your code.


Simple Tests

Nothing is more important than keeping tests simple.

If your tests are hard to run or hard to interpret, then you might as well not use TDD.


UI Testing

You don't test the UI, instead, you design your code so that it can be tested in a non-interactive manner. After all, you don't need to test an edit control to know if it works. That's someone else's job. You just need to test the data that goes into and out of the edit control. Put that in a separate, non-visual class, and then you are okay. This is very much at the heart of Unit Testing philosophy.


Build Process


Exception Handling


Setup TearDown


Fixtures


Suites

Test Suites

MySuite := TTestSuite.Create('This is my suite');
MySuite.AddTests(TMyTest01);
MySuite.AddTests(TMyTest02);

But mostly you just do this:

TestFramework.RegisterTest(TMyTest01.Suite);
TestFramework.RegisterTest(TMyTest02.Suite);
GUITestRunner.RunRegisteredTests;

Single Unit?


Mock Objects

This section is in its own set of files, found here.


Excuses

Excuses for not Programming

Found in Pragmatic Programmer.

  • It takes to long to write tests: This is definitely true if you wait until the end. Then it will take a long time to cover your whole app with tests. Instead, write tests incrementally as you go along. Then you are sure that your code works, and you end up saving time because there will be less debugging.
  • Its not my job to create and run tests. Oh really? Creating quality code is not part of the description of your job? Why is it your job to use the debugger, but not your job to write tests that eliminate the need to use the debugger.
  • I'll put QA out of work. No you won't. Unit Testing doesn't solve all coders problems. It's just a technique for eliminating a certain kind of bug. Other tests will still be necessary. Integration tests, functional tests, acceptance tests.

Summary