Test Driven Development An approach to writing better code Jimmy Zimmerman Intel Corporation

Preview:

Citation preview

Test Driven Development

An approach to writing better code

Jimmy Zimmerman

Intel Corporation

Outline

• What is TDD?• Why perform TDD?• Myths about TDD• How do we do TDD?• When NOT to perform TDD• Tools for TDD• Example of TDD• Q&A

The Problem

• Over 50% of all software projects are initiated and then canceled.

• Over 80% of software projects completed suffer massive* cost and time overruns.

• Quality, or the lack thereof, is a major issue. Code is bloated, buggy, and marginally useful.

* Over 100% of budget and/or time.West, pg 87

The Solution (Isn’t)

• building / using new tools.

• creating more elaborate documents.

• adding more layers of process

• “better” programming languages

The Solution (is)

producing “better people” aka Better Programmers, regardless of method or intended use of the application.

FACT 1

The most important factor in software work is not the tools and processes used by the programmers but rather the quality of the programmers themselves.

I. What is TDD?

• Definition: Test Driven Development is the practice of utilizing tests to document and define the behavior of software.

• Tests DRIVE the design of software, not follow already designed software.

• Design documentation is finalized from the tests, not used to create the tests from.

FACT 2

The most important part of writing programs is creating the tests that describe the behavior of the software and not the software itself.

II. Why perform TDD?

• Eliminates Duplication of Code

• Shared Responsibility

• Common Language

• Simplest Solution Possible

• Modularization

• A “Gateway Habit”

Eliminates Duplication of Code

• Code duplication epitomizes bad software.• Tests describe the behavior of the code

we are writing.• When writing the code, we will find

common behavior and refactor.• Tests provide the ability to reliably

refactor existing code.• Tests ensure the behavior of the code

does not change after refactoring.

Shared Responsibility

• Application code is the responsibility of all programmers on a project.

• Code that is unfamiliar to a programmer is hard to learn. Tests document the behavior of code, making it easier to learn.

• A test allows the code to be modified by any developer. This prevents “pigeon-holing” and overall increases speed of development.

• The more peer review of code by the greatest number of programmers the better.

Common Language

• Programs are written in code. The code has a language. Developers understand the language. Code is deterministic.

• The tests are written with the common language of the application.

• A single language documents the behavior of the application and the implementation of the behavior.

• Translations of any kind introduce errors and misunderstandings to the meaning.

Simplest Solution Possible

• Software is complex. The simpler the code the more resilient and easier it is to change.

• Tests define requirements. Writing code should satisfy the requirements no less and no more.

• Every line of code requires maintenance. Adding more code adds to the maintenance by adding complexity.

• Program for today. Worry about tomorrow when it comes.

• “Simplest Solution that Works is NOT the first stupid idea that pops into your head” – Udi Dahan

Program for Today (expanded)

Q: Why? Isn’t it better to plan for tomorrow?

A: No– Planning is not implementing.– Tomorrow might not come.– When you finally need it, you probably will

know more about how to do it correctly.– Tests mitigate the cost of change over time.

Cost of ChangeC

ost

of C

ha

ng

e

Time

Cost 1 Cost 2

FACT 3

Adding features when they are needed saves more money over time than it costs to build before they are needed.

Modularization

• Good software depends on building small single use modules.

• While the technology of modules changes (methods, messages, global functions, APIs) each provides a quantifiable set of behaviors.

• Once you start to TDD, you will find that your code will naturally become more modular to support the ease of testing.

A “Gateway Habit”

TDD is the foundation that enables other habits of successful development processes.– Frequent, incremental releases (less is more)– Peer review– Early customer feedback– KISS– Refactoring– Agile methods

III. Myths about TDD

1. It’s just for OOP

2. It’s a replacement for good programming skill

3. It’s hard to do

4. I don’t have time

5. Testing is for QA

Myth 1: It’s just for OOP

NO.– TDD is about a mindset and not a technology.– While objects make it easier to program

complex applications, all programs benefit from writing tests. They act as an outline for what you want to do.

– Tests can work with any language and platform. (I’ve seen TDD done in x86 assembler at school!)

Myth 2: It’s a replacement for good programming skill

NO.– No matter how good you are, you will make a

mistake eventually.– Even if you never make mistakes someone

else will need to maintain your code. It is unlikely they can know all the behaviors your code has.

– This is the most important of all programmer skills and not a replacement for skill!

Myth 3: It’s hard to do

INCORRECT.– It makes your job easier by breaking down

your work into manageable steps.– It allows you to make changes to existing

code easily.– It does take discipline however.

(so yes in that it’s “hard” to not be lazy )

Myth 4: I don’t have time

WRONG.– Tests prevent bugs. Less bugs make for more

time over the life of the application.– An ounce of prevention is worth a pound of

cure.– They allow someone else to help you without

making your life harder.

Myth 5: Testing is for QA

WRONG.– QA is not there to find bugs. They are there to

confirm the behavior of application meets the agreed functionality.

– A developer is responsible for writing secure, bug free, and reliable code that provides the exact functionality the program specifies.

– A bug should be an exceptionally rare occurrence in QA. Tests are the tool to make them rare.

IV. How do we do TDD?

1. Write the test code.2. Compile the test code (this should fail)3. Implement just enough to compile.4. Run and watch it fail5. Implement just enough to make the first test

pass.6. Run the test and watch it pass.7. Refactor for clarity and to eliminate duplication.8. Repeat from top.

Fact 4

Red -> Green -> Refactor

Small verifiable steps are better. They provide immediate feedback that builds confidence in code. When something goes wrong, you will immediately know where and why.

V. When NOT to perform TDD

TDD requires an upfront investment in resources. Over the course of a project development cycle this amount of effort is a very small percentage of the overall work. The end of the cycle does not allow the cost to be minimized and therefore it is inappropriate to begin TDD during that phase.

Tools for TDD

• Tools do not make or break TDD, they only aid it (remember it’s a mindset).

• Tools depend on platform.– nUnit– mbUnit– jUnit– Page tracing– ACT– Invent a tool!

Example of TDD

Interactive Example using Visual Studio.Net 2003 and nUnit.

• Creating an unbounded stack

• Push/Pop/IsEmpty capability

• Properly limits bound access

Task 1

A

B

C

A

B

C

Initial State Final State

Push

Operation

IsEmpty = falseIsEmpty = false

Task 2

A

A

Initial State Final State

Pop

Operation

IsEmpty = trueIsEmpty = false

Task 3

Initial State Final State

Pop

Operation

IsEmpty = trueIsEmpty = true

EXCEPTION