55
TEST-DRIVEN DEVELOPMENT Presenting TDD 2009-04-29 Brian Rasmussen http://www.linkedin.com/in/brianrasmussen

Test-Driven Development (TDD)

Embed Size (px)

DESCRIPTION

These are my slides for a TDD presentation on 2009-04-29

Citation preview

Page 1: Test-Driven Development (TDD)

TEST-DRIVEN DEVELOPMENTPresenting TDD

2009-04-29

Brian Rasmussenhttp://www.linkedin.com/in/brianrasmussen

Page 2: Test-Driven Development (TDD)

AGENDA

Answers to the WH-words (WHO – WHAT – WHERE)

Where to begin

The Turn …

… the Twist

Excuses and Common Traps

Where to go from here

Page 3: Test-Driven Development (TDD)

What is TDD

Page 4: Test-Driven Development (TDD)

WHAT IS TDD

Test-Driven Development (or test driven design) is a methodology.

Common TDD misconception: TDD is not about testing

TDD is about design and development

By testing first you design your code

Page 5: Test-Driven Development (TDD)

WHAT IS TDD

Short development iterations.

Based on requirement and pre-written test cases.

Produces code necessary to pass that iteration's test.

Refactor both code and tests.

The goal is to produce working clean code that fulfills requirements.

Page 6: Test-Driven Development (TDD)

TEST-DRIVEN DEVELOPMENT

Test-driven development (TDD) is a software development technique that uses short development iterations based on pre-written test cases that define desired improvements or new functions. Each iteration produces code necessary to pass that iteration's tests. Finally, the programmer or team refactors the code to accommodate changes. A key TDD concept is that preparing tests before coding facilitates rapid feedback changes. Note that test-driven development is a software design method, not merely a method of testing.

Page 7: Test-Driven Development (TDD)

HOW DOES TDD HELP

TDD helps you produce clean working code that fulfills requirements

Write Test Code Code that fulfills requirements

Write Functional Code Working code that fulfills requirements

Refactor Clean working code that fulfills requirements

Page 8: Test-Driven Development (TDD)

ORIGIN

eXtreme Programming (XP) 1999 Kent Beck, Martin Fowler and others…

Page 9: Test-Driven Development (TDD)

TDD BASICS - UNIT TESTING

Red, Green, Refactor

Make it Fail No code without a failing test

Make it Work As simply as possible

Make it Better Refactor

Page 10: Test-Driven Development (TDD)

TDD CYCLE

New require-ment

Write new test

Run tests

Write new codeRun tests

Refactor

Run tests

Make it Fail

Make it Work

Make it Better

Page 11: Test-Driven Development (TDD)

TDD CYCLE

Write Test Code Guarantees that every functional code is testable Provides a specification for the functional code Helps to think about design Ensure the functional code is tangible

Write Functional Code Fulfill the requirement (test code) Write the simplest solution that works Leave Improvements for a later step The code written is only designed to pass the test

no further (and therefore untested code is not created).

Refactor Clean-up the code (test and functional) Make sure the code expresses intent Remove code smells Re-think the design Delete unnecessary code

Page 12: Test-Driven Development (TDD)

Why TDD

Page 13: Test-Driven Development (TDD)

WHY / BENEFITS

Confidence in change Increase confidence in code Fearlessly change your code

Document requirements

Discover usability issues early

Regression testing = Stable software = Quality software

Page 14: Test-Driven Development (TDD)

WHERE DOES IT HURT

Requirements Coding Integration Testing Support0%

20%

40%

60%

80%

100%

0

1000

2000

3000

4000

5000

6000

7000

8000

9000

10000

% of Defects Introduced Cost to Fix a Defect

% d

efec

ts c

reat

ed

Thou

sand

$s

The pain is here! This is too late…

Page 15: Test-Driven Development (TDD)

MS:

VS

MS:

MSN

MS:

Windows

IBM: D

rivers

0%

20%

40%

60%

80%

100%

120%

140%

160%

Time To Code FeatureTime To Code Feature us-ing TDDDefect density of teamDefect density of team us-ing TDD

IS TDD A WASTE OF TIME (MICROSOFT RESEARCH)

Major quality improvement for minor time investment

Page 16: Test-Driven Development (TDD)

How to

Page 17: Test-Driven Development (TDD)

REMEMBER - THERE ARE OTHER KINDS OF TESTS

Unit test (Unit) Integration test (Collaboration) User interface test (Frontend, ex. WatiN) Regression test (Continuous Integration) …, System, Performance, Stress, Usability, …

Test types: Black-box test White-box test

The only tests relevant to TDD is Black-box Unit Testing

Page 18: Test-Driven Development (TDD)

DIFFICULT SCENARIOS TO UNIT TEST

Closed Object Models (Sharepoint, Silverlight) Client – server architecture

Communicating Across a Network

An out-of-process call Includes talking to databases and Web Services.

UI GUI interaction

Touching the File System Legacy Code Requires the Environment to be configured

Page 19: Test-Driven Development (TDD)

HOW TO DO TDD

… on my component A? Unit Test A, but what about B, C, D…?

CB

DE

A

Page 20: Test-Driven Development (TDD)

HOW TO DO TDD

… on my component A?

If my component reference… My coworkers component A third party component A very slow component (Database, Web service) A component with complex set up A component with exceptional behavior (Exception) A remote component (Remoting) Circular dependency

Do I have to wait on these components to be created and/or tested?

This, and the previous two slides,are all thoughts on implementing tests on existing code.

This is all White-box Unit- or Integration Testing and has therefore nothing to do with TDD.

In TDD you write a Black-box Unit test that fails, first,and worry about the code implementation later.

Page 21: Test-Driven Development (TDD)

SINGLE MOST IMPORTANT THINGWHEN LEARNING TDD

Do notwrite the code in your

headbefore you write the

test

Page 22: Test-Driven Development (TDD)

SINGLE MOST IMPORTANT THING WHEN LEARNING TDD

When you first start at doing TDD you "know" what the design should be. You "know" what code you want to write. So you write a test that will let you write that bit of code.

When you do this you aren't really doing TDD – since you are writing the code first (even if the code is only in your head )

It takes some time to (and some poking by clever folk) to realize that you need to focus on the test. Write the test for the behavior you want - then write the minimal code needed to make it pass - then let the design emerge through refactoring. Repeat until done.

Page 23: Test-Driven Development (TDD)

Where to begin

Page 24: Test-Driven Development (TDD)

UNBOUNDED STACK EXAMPLE

Requirement: FILO / LIFO messaging system

Brainstorm a list of tests for the requirement: Create a Stack and verify that IsEmpty is true. Push a single object on the Stack and verify that IsEmpty is false. Push a single object, Pop the object, and verify that IsEmpty is true. Push a single object, remembering what it is; Pop the object, and verify

that the two objects are equal. Push three objects, remembering what they are; Pop each one, and verify

that they are removed in the correct order. Pop a Stack that has no elements. Push a single object and then call Top. Verify that IsEmpty is false. Push a single object, remembering what it is; and then call Top. Verify

that the object that is returned is the same as the one that was pushed. Call Top on a Stack with no elements.

Page 25: Test-Driven Development (TDD)

UNBOUNDED STACK EXAMPLE

Choosing the First Test? The simplest. The essence.

Answers: If you need to write code that is untested, choose a

simpler test.

If the essence approach takes to much time to implement, choose a simpler test.

Page 26: Test-Driven Development (TDD)

UNBOUNDED STACK EXAMPLE

Anticipating future tests, or not?

Answers: In the beginning, focus on the test you are writing,

and do not think of the other tests.

As you become familiar with the technique and the task, you con increase the size of the steps.

But remember still, no written code must be untested.

Page 27: Test-Driven Development (TDD)

Unbounded stack example

Page 28: Test-Driven Development (TDD)

UNBOUNDED STACK EXAMPLE

As we were implementing the sixed test, a few additional tests came to mind, so we need to add them to our test list.

We want to add tests to verify that the Stack works when the arguments are equal to null. The new tests are as follows:

Push null onto the Stack and verify that IsEmpty returns false. Push null onto the Stack, Pop the Stack, and verify that the value

returned is null. Push null onto the Stack, call Top, and verify that the value returned is

null.

Page 29: Test-Driven Development (TDD)

The Turn …

Page 30: Test-Driven Development (TDD)

WHY DON’T YOU DO TDD, STILL

Why, when TDD was born a decade ago? The one and only reason: #1: Learning curve…

So why am I telling you this today? Something happened in the last year…

Page 31: Test-Driven Development (TDD)

TECHNIQUES YOU NEEDED TO KNOW ABOUT

Interfaces Dependency Injection Test Doubles (Mock Objects) Mocking Framework. The builder and fluent interface patterns. …

Not a chance – you still need to know about: Refactoring

Page 32: Test-Driven Development (TDD)

THE OLD WAY VS THE NEW WAY

Either (the old way)“Mock”

Using Interfaces, Dependency Injection andTest Doubles (Mock Objects)

Or (the new way)“Isolate” and “Fake”

Using Typemock Isolatorand AAA - The "Arrange-act-assert" pattern

Page 33: Test-Driven Development (TDD)

WHY “ISOLATE” AND / OR “FAKE” AT ALL

… when you can hand-write mocks yourself.

ASP.NET MVC example

Page 34: Test-Driven Development (TDD)

WHY “ISOLATE” AND / OR “FAKE” AT ALL

… when you can hand-write mocks yourself.

ASP.NET MVC AccountControllerTest file contains 25 tests. The mocking code starts at line 376 and goes on until line 668 (the end

of the file). That's 293 lines of mocking code, some of it contains logic.

Rewriting all this with Isolator code Ends at line 392

I'll let you do the math. I wrote mock code like that before. Can you believe my mocking code

even contained bugs? I had to fix those as well.

It's a waste of time.Start using an isolation framework now.

Page 35: Test-Driven Development (TDD)

WHY BUY WHEN YOU CAN GET IT FOR FREE

Typemock (Commercial) vs. other frameworks. The "free" products are not called free, they are open-source projects. They are built in most cases by a single person, and maintained by the

community if they are successful. There's a lot of effort and love put into that. What's the return? There's

the great satisfaction someone finds your software useful (Hey, that also goes for commercial products).

Ayende, creator of Rhino Mocks and Daniel, creator of Moq, put a lot of hours into feature requests and support, but there's a limit to what they can do.

Take a look at Ayende's slogan on his blog: "Send me a patch for this".

Don't be a whiner. Take responsibility. Compare the good, bad and ugly. And pick what is right for you, not because it's what you can afford, but for what it will save you, give you back or help you outperform your competitors.

Of course you get what you pay for (Nothing + More nothing = Nothing).

Page 36: Test-Driven Development (TDD)

TYPEMOCK™

Established 2005, privately owned Typemock Isolator Thousands of customers (Fortune 500) Tens of thousands licenses sold

Page 37: Test-Driven Development (TDD)

TYPEMOCK.NET HISTORY

The Typemock Isolator product supports three sets of API in order to fake dependencies:

Reflective Mocks String based API (Oldest framework).

Natural Mocks Record-Replay but strongly typed (Old framework).

Typemock Isolator Arrange Act Assert (AAA) Syntax (Latest API version - you are

encouraged to use this).

Page 38: Test-Driven Development (TDD)

ARRANGE ACT ASSERT (AAA)

The “Arrange-act-assert” pattern in the field of mock frameworks represents us trying to return to basics.

Moq did that nicely by showing a way that leads there, and it is being taken gladly by Rhino and Typemock Isolator.

AAA is guidance because there was an outcry (a silent, vote of feet) that record-replay is not cutting it – it’s too confusing for non-experts. It’s too technical. and it does not lend itself to the way people want to work. So most people didn’t use it.

Page 39: Test-Driven Development (TDD)

… the Twist

Page 40: Test-Driven Development (TDD)

Typemock Isolator Demo

Page 41: Test-Driven Development (TDD)

Excuses

Page 42: Test-Driven Development (TDD)

TOP FIVE EXCUSES FOR NOT UNIT TESTING

1. I don’t have time to unit test.2. The client pays me to develop code, not write unit

test.3. I am supporting a legacy application without unit

tests.4. QA and User Acceptance Testing is far more

effective in finding bugs.5. I don’t know how to unit test, or I don’t know how

to write good unit tests.

Page 43: Test-Driven Development (TDD)

WHEN DO YOU THINK YOU'LL INTRODUCE UNIT TESTING

A common answer to this question: "We're in a middle of a project right now. We'll wait two months until it

completes, then we'll have time".

If you gave me this answer, I won't believe you. Here's why:

If I came to you in two months and asked what has changed since last time, you'll give me the same answer.

That's because development is always done under pressure.

Page 44: Test-Driven Development (TDD)

WHEN DO YOU THINK YOU'LL INTRODUCE UNIT TESTING

In two months time, you'll be up to your neck in fixing bugs, running away from QA reports. You'll fix those bugs, and eat away at the time you thought you'd have when the project completes. And when it does complete (late), and you think it's over, you'll start receiving bug reports from the customer. Guess what? no time to start unit testing then either.

Let's face it, there is never a good time to start unit-testing, or making any change, for that matter. So, start today. Write your first unit tests. Change is painful, and you'd rather delay that. But in agile, we say: if it's painful, do it first.

Page 45: Test-Driven Development (TDD)

TEST CODE IS JUST CODE - COMMON TRAPS

Some Anti-Patterns to avoid and some techniques for making sure Test Code doesn't slow you down:

Cut & Paste Refactor test code

Poor Encapsulation The builder and fluent interface patterns are very useful here

Bloated SetUp Isolation framework / Dependency Injection and Test Doubles

Too hard to write the Test Refactor production code

Code Integration Test Pain Remember Integration Testing as well

Page 46: Test-Driven Development (TDD)

CLASSICISTS V MOCKIST V ISOLATOR

Classicists The classical TDD style is to use real objects if possible and a double if

it's awkward to use the real thing. So a classical TDDer would use a real warehouse and a double for the mail service. The kind of double doesn't really matter that much.

Mockist A mockist TDD practitioner, however, will always use a mock for any

object with interesting behavior. In this case for both the warehouse and the mail service.

Isolator and Fake An isolator TDD practitioner, will always “isolate” or “fake” any object

with interesting behavior. In this case for both the warehouse and the mail service.

The Classicists does White-box Integration testingFirst generation TDD

The Mockist does White-box Unit testingSencond generation TDD

The Isolator and Fake does Black-box Unit testingThird generation TDD

Page 47: Test-Driven Development (TDD)

INTRODUCING BDD

Behaviour-Driven Development (BDD) By Dan North BDD is another variation on TDD that tends to use mockist testing

Test method names should be sentences A simple sentence template keeps test methods

focused This sentence template – The class should do something – means you can only

define a test for the current class. This keeps you focused. If you find yourself writing a test whose name doesn’t fit this template, it suggests the behaviour may belong elsewhere.

An expressive test name is helpful when a test fails “Behaviour” is a more useful word than “test”. Determine the next most important behaviour. Requirements are behaviour, too. BDD provides a “ubiquitous language” for analysis. Acceptance criteria should be executable.

Page 48: Test-Driven Development (TDD)

WHEN TO USE TDD/BDD

When you have to implement a new functional requirement, or make a requirement up yourself.

Note: When you want to change existing code, first write covering Unit Tests (white box testing).Then use TDD to add new functionality.

Page 49: Test-Driven Development (TDD)

TOOLS YOU NEED TO KNOW ABOUT

Continuous Integration

Build Automation Tools MSBuild Nant FinalBuilder

CI Servers Team System / Team Foundation Server TeamCity (R#) CCnet (CruiseControl.NET) FinalBuilder Server

Page 50: Test-Driven Development (TDD)

TOOLS YOU NEED TO KNOW ABOUT

Visual Studio IntegrationRefactoring R# (ReSharper) Code Rush

Page 51: Test-Driven Development (TDD)

TOOLS YOU NEED TO KNOW ABOUT

Isolation / Mocking Frameworks for .net

Open Source Rhino Mocks for .NET NMock for .NET Moq for .Net

Commercial (costs money but worth it) Typemock Isolator Typemock Isolator For SharePoint

Page 52: Test-Driven Development (TDD)

Where to go from here

Page 53: Test-Driven Development (TDD)

WHERE TO GO FROM HERE

You don’t have to start big Start new tasks with TDD Add Tests to code that you need to change or

maintain – but only to small parts Proof of concept

If it's worth building, it's worth testing.If it's not worth testing,

why are you wasting your time working on it?

Page 54: Test-Driven Development (TDD)

LINKS

Books Test-Driven Development in Microsoft® .NET (http://www.amazon.co.uk/gp/product/0735619484) Test-Driven Development by Kent Beck (C++) (http://www.amazon.co.uk/gp/product/0321146530)

Blog The Typemock Insider Blog (http://blog.typemock.com/)

Unit test study from Microsoft Research: http://research.microsoft.com/en-us/projects/esm/nagappan_tdd.pdf

Typemock http://www.typemock.com/

Unit testing Silverlight: http://www.codeplex.com/CThru

Other links: http://en.wikipedia.org/wiki/Test-driven_development http://www.testdriven.com/ http://www.mockobjects.com/ - Online TDD book: http://www.mockobjects.com/book/index.html http://www.martinfowler.com/articles/mocksArentStubs.html http://dannorth.net/introducing-bdd http://behaviour-driven.org/Introduction

Page 55: Test-Driven Development (TDD)

Q&A