Praise for Growing Object-Oriented Software, Guided by Tests

“The authors of this book have led a revolution in the craft of programming by controlling the environment in which software grows. Their Petri dish is the mock object, and their microscope is the unit test. This book can show you how these tools introduce a repeatability to your work that would be the envy of any scientist.”

Ward Cunningham

“At last a book, suffused with code, that exposes the deep symbiosis between TDD and OOD. The authors, pioneers in test-driven development, have packed it with principles, practices, heuristics, and (best of all) anecdotes drawn from their decades of professional experience. Every software craftsman will want to pore over the chapters of worked examples and study the advanced testing and design principles. This one’s a keeper.”

Robert C. Martin

“Design is often discussed in depth, but without empiricism. Testing is often promoted, but within the narrow definition of quality that relates only to the presence or absence of defects. Both of these perspectives are valuable, but each on its own offers little more than the sound of one hand clapping. Steve and Nat bring the two hands together in what deserves—and can best be described as—applause. With clarity, reason, and humour, their tour de force reveals a view of design, testing, code, objects, practice, and process that is compelling, practical, and overflowing with insight.”

Kevlin Henney, co-author of Pattern-Oriented Software Architecture and 97 Things Every Programmer Should Know

“Steve and Nat have written a wonderful book that shares their software craftsmanship with the rest of the world. This is a book that should be studied rather than read, and those who invest sufficient time and energy into this effort will be rewarded with superior development skills.”

David Vydra, publisher, testdriven.com

“This book presents a unique vision of test-driven development. It describes the mature form of an alternative strain of TDD that sprang up in London in the early 2000s, characterized by a totally end-to-end approach and a deep emphasis on the messaging aspect of objects. If you want to be an expert in the state of the art in TDD, you need to understand the ideas in this book.”

Michael Feathers

“With this book you’ll learn the rhythms, nuances in thinking, and effective programming practices for growing tested, well-designed object-oriented applications from the masters.”

Rebecca Wirfs-Brock

Growing Object-Oriented Software, Guided by Tests

Steve Freeman and Nat Pryce

image

Upper Saddle River, NJ • Boston • Indianapolis • San Francisco
New York • Toronto • Montreal • London • Munich • Paris • Madrid
Cape Town • Sydney • Tokyo • Singapore • Mexico City

Many of the designations used by manufacturers and sellers to distinguish their products are claimed as trademarks. Where those designations appear in this book, and the publisher was aware of a trademark claim, the designations have been printed with initial capital letters or in all capitals.

The authors and publisher have taken care in the preparation of this book, but make no expressed or implied warranty of any kind and assume no responsibility for errors or omissions. No liability is assumed for incidental or consequential damages in connection with or arising out of the use of the information or programs contained herein.

The publisher offers excellent discounts on this book when ordered in quantity for bulk purchases or special sales, which may include electronic versions and/or custom covers and content particular to your business, training goals, marketing focus, and branding interests. For more information, please contact:

U.S. Corporate and Government Sales
(800) 382–3419
[email protected]

For sales outside the United States please contact:

International Sales
[email protected]

Visit us on the Web: informit.com/aw

Library of Congress Cataloging-in-Publication Data:

Freeman, Steve, 1958-
  Growing object-oriented software, guided by tests / Steve Freeman and Nat Pryce.
       p. cm.
  ISBN 978-0-321-50362-6 (pbk. : alk. paper)  1.  Object-oriented programming
(Computer science) 2.  Computer software--Testing.  I. Pryce, Nat. II. Title.
  QA76.64.F747 2010
  005.1’17--dc22
                                                             2009035239

Copyright © 2010 Pearson Education, Inc.

All rights reserved. Printed in the United States of America. This publication is protected by copyright, and permission must be obtained from the publisher prior to any prohibited reproduction, storage in a retrieval system, or transmission in any form or by any means, electronic, mechanical, photocopying, recording, or likewise. For information regarding permissions, write to:

Pearson Education, Inc
Rights and Contracts Department
501 Boylston Street, Suite 900
Boston, MA 02116
Fax (617) 671 3447

ISBN-13: 978–0–321–50362-6
ISBN-10: 0–321–50362–7
Text printed in the United States on recycled paper at RR Donnelley in Crawfordsville, Indiana.
Sixth printing June 2012

To Paola, for all her support; to Philip, who sometimes missed out

—Steve

To Lamaan who put up with me spending time writing this book, and Oliver Tarek who did not

—Nat

Contents

Foreword

Preface

Acknowledgments

About the Authors

Part I: Introduction

Chapter 1: What Is the Point of Test-Driven Development?

Software Development as a Learning Process

Feedback Is the Fundamental Tool

Practices That Support Change

Test-Driven Development in a Nutshell

The Bigger Picture

Testing End-to-End

Levels of Testing

External and Internal Quality

Chapter 2: Test-Driven Development with Objects

A Web of Objects

Values and Objects

Follow the Messages

Tell, Don’t Ask

But Sometimes Ask

Unit-Testing the Collaborating Objects

Support for TDD with Mock Objects

Chapter 3: An Introduction to the Tools

Stop Me If You’ve Heard This One Before

A Minimal Introduction to JUnit 4

Hamcrest Matchers and assertThat()

jMock2: Mock Objects

Part II: The Process of Test-Driven Development

Chapter 4: Kick-Starting the Test-Driven Cycle

Introduction

First, Test a Walking Skeleton

Deciding the Shape of the Walking Skeleton

Build Sources of Feedback

Expose Uncertainty Early

Chapter 5: Maintaining the Test-Driven Cycle

Introduction

Start Each Feature with an Acceptance Test

Separate Tests That Measure Progress from Those That Catch Regressions

Start Testing with the Simplest Success Case

Write the Test That You’d Want to Read

Watch the Test Fail

Develop from the Inputs to the Outputs

Unit-Test Behavior, Not Methods

Listen to the Tests

Tuning the Cycle

Chapter 6: Object-Oriented Style

Introduction

Designing for Maintainability

Internals vs. Peers

No And’s, Or’s, or But’s

Object Peer Stereotypes

Composite Simpler Than the Sum of Its Parts

Context Independence

Hiding the Right Information

An Opinionated View

Chapter 7: Achieving Object-Oriented Design

How Writing a Test First Helps the Design

Communication over Classification

Value Types

Where Do Objects Come From?

Identify Relationships with Interfaces

Refactor Interfaces Too

Compose Objects to Describe System Behavior

Building Up to Higher-Level Programming

And What about Classes?

Chapter 8: Building on Third-Party Code

Introduction

Only Mock Types That You Own

Mock Application Objects in Integration Tests

Part III: A Worked Example

Chapter 9: Commissioning an Auction Sniper

To Begin at the Beginning

Communicating with an Auction

Getting There Safely

This Isn’t Real

Chapter 10: The Walking Skeleton

Get the Skeleton out of the Closet

Our Very First Test

Some Initial Choices

Chapter 11: Passing the First Test

Building the Test Rig

Failing and Passing the Test

The Necessary Minimum

Chapter 12: Getting Ready to Bid

An Introduction to the Market

A Test for Bidding

The AuctionMessageTranslator

Unpacking a Price Message

Finish the Job

Chapter 13: The Sniper Makes a Bid

Introducing AuctionSniper

Sending a Bid

Tidying Up the Implementation

Defer Decisions

Emergent Design

Chapter 14: The Sniper Wins the Auction

First, a Failing Test

Who Knows about Bidders?

The Sniper Has More to Say

The Sniper Acquires Some State

The Sniper Wins

Making Steady Progress

Chapter 15: Towards a Real User Interface

A More Realistic Implementation

Displaying Price Details

Simplifying Sniper Events

Follow Through

Final Polish

Observations

Chapter 16: Sniping for Multiple Items

Testing for Multiple Items

Adding Items through the User Interface

Observations

Chapter 17: Teasing Apart Main

Finding a Role

Extracting the Chat

Extracting the Connection

Extracting the SnipersTableModel

Observations

Chapter 18: Filling In the Details

A More Useful Application

Stop When We’ve Had Enough

Observations

Chapter 19: Handling Failure

What If It Doesn’t Work?

Detecting the Failure

Displaying the Failure

Disconnecting the Sniper

Recording the Failure

Observations

Part IV: Sustainable Test-Driven Development

Chapter 20: Listening to the Tests

Introduction

I Need to Mock an Object I Can’t Replace (without Magic)

Logging Is a Feature

Mocking Concrete Classes

Don’t Mock Values

Bloated Constructor

Confused Object

Too Many Dependencies

Too Many Expectations

What the Tests Will Tell Us (If We’re Listening)

Chapter 21: Test Readability

Introduction

Test Names Describe Features

Canonical Test Structure

Streamline the Test Code

Assertions and Expectations

Literals and Variables

Chapter 22: Constructing Complex Test Data

Introduction

Test Data Builders

Creating Similar Objects

Combining Builders

Emphasizing the Domain Model with Factory Methods

Removing Duplication at the Point of Use

Communication First

Chapter 23: Test Diagnostics

Design to Fail

Small, Focused, Well-Named Tests

Explanatory Assertion Messages

Highlight Detail with Matchers

Self-Describing Value

Obviously Canned Value

Tracer Object

Explicitly Assert That Expectations Were Satisfied

Diagnostics Are a First-Class Feature

Chapter 24: Test Flexibility

Introduction

Test for Information, Not Representation

Precise Assertions

Precise Expectations

“Guinea Pig” Objects

Part V: Advanced Topics

Chapter 25: Testing Persistence

Introduction

Isolate Tests That Affect Persistent State

Make Tests Transaction Boundaries Explicit

Testing an Object That Performs Persistence Operations

Testing That Objects Can Be Persisted

But Database Tests Are S-l-o-w!

Chapter 26: Unit Testing and Threads

Introduction

Separating Functionality and Concurrency Policy

Unit-Testing Synchronization

Stress-Testing Passive Objects

Synchronizing the Test Thread with Background Threads

The Limitations of Unit Stress Tests

Chapter 27: Testing Asynchronous Code

Introduction

Sampling or Listening

Two Implementations

Runaway Tests

Lost Updates

Testing That an Action Has No Effect

Distinguish Synchronizations and Assertions

Externalize Event Sources

Afterword: A Brief History of Mock Objects

Appendix A: jMock2 Cheat Sheet

Appendix B: Writing a Hamcrest Matcher

Bibliography

Index

Foreword

Kent Beck

One of the dilemmas posed by the move to shorter and shorter release cycles is how to release more software in less time—and continue releasing indefinitely. A new perspective is necessary to resolve this dilemma. More than a shift in techniques is needed.

Growing Object-Oriented Software, Guided by Tests presents such a new perspective. What if software wasn’t “made,” like we make a paper airplane—finish folding it and fly it away? What if, instead, we treated software more like a valuable, productive plant, to be nurtured, pruned, harvested, fertilized, and watered? Traditional farmers know how to keep plants productive for decades or even centuries. How would software development be different if we treated our programs the same way?

I am most impressed by how this book presents both the philosophy and mechanics of such a shift in perspective. It is written by practitioners who code—and teach others to code—well. From it you can learn both how to program to sustain productivity and how to look at your programs anew.

The style of test-driven development presented here is different from what I practice. I can’t yet articulate the difference, but I have learned from the clear, confident presentation of the authors’ techniques. The diversity of dialects has given me a new source of ideas to further refine my own development. Growing Object-Oriented Software, Guided by Tests, presents a coherent, consistent system of development, where different techniques support each other.

I invite you to read Growing Object-Oriented Software, Guided by Tests, to follow along with the examples, to learn how the authors think about programming and how they program. The experience will enrich your software development style, help you program—and, just as important, see your programs differently.

Preface

What Is This Book About?

This book is a practical guide to the best way we’ve found to write object-oriented software: test-driven development (TDD). It describes the processes we follow, the design principles we strive for, and the tools we use. It’s founded on our decades of experience, working with and learning from some of the best programmers in the world.

Within the book, we address some of the questions and confusions we see coming up on project after project. How do I fit test-driven development into a software project? Where do I start? Why should I write both unit and end-to-end tests? What does it mean for tests to “drive” development? How do I test difficult feature X?

This book is also very much about design and the way our approach to design informs our approach to TDD. If there’s one thing we’ve learned, it’s that test-driven development works best when taken as a whole. We’ve seen teams that can do the raw practices (writing and running tests) but struggle with the result because they haven’t also adopted the deeper processes that lie behind it.

Why “Growing” Object-Oriented Software?

We used the term “growing” because it gives a sense of how we develop incrementally. We have something working at all times, making sure that the code is always as well-structured as possible and thoroughly tested. Nothing else seems to be as effective at delivering systems that work. As John Gall wrote in [Gall03], “A complex system that works is invariably found to have evolved from a simple system that works.”

“Growing” also hints at the biological quality we see in good software, the sense of coherence at every level of structure. It ties into our approach to object orientation which follows Alan Kay’s1 concept of objects being similar to biological cells that send each other messages.

1. Alan Kay was one of the authors of Smalltalk and coined the term “object-oriented.”

Why “Guided” by Tests?

We write tests first because we find that it helps us write better code. Writing a test first forces us to clarify our intentions, and we don’t start the next piece of work until we have an unambiguous description of what it should do. The process of writing a test first helps us see when a design is too rigid or unfocused. Then, when we want to follow through and fix a design flaw, the tests give us a safety net of regression coverage.

We use the term “guided” because the technique still requires skill and experience. We found test-driven development to be an effective design support tool—once we’d learned how to develop incrementally and to “listen to the tests.” Like any serious design activity, TDD requires understanding and sustained effort to work.

We’ve seen teams that write tests and code at about the same time (and even teams that write the tests first) where the code is a mess and the tests just raise the cost of maintenance. They’d made a start but hadn’t yet learned that the trick, as the title of the book suggests, is to let the tests guide development. Use the contents of the tests to stay focused on making progress and feedback from the tests to raise the quality of the system.

What about Mock Objects?

Our original motivation for writing the book was to finally explain the technique of using mock objects,2 which we often see misunderstood. As we got deeper into writing, we realized that our community’s discovery and use of mock objects was actually an expression of our approach to writing software; it’s part of a larger picture.

2. Mock objects are substitute implementations for testing how an object interacts with its neighbors.

In the course of the book, we will show how the mock objects technique works, using the jMock library. More specifically, we’ll show where it fits into the TDD process and how it makes sense in the context of object-oriented development.

Who Is This Book For?

We wrote this book for the “informed reader.” It’s intended for developers with professional experience who probably have at least looked at test-driven development. When writing, we imagined we were explaining techniques to a colleague who hadn’t come across them before.

To make room for the deeper material we wanted to cover, we’ve assumed some knowledge of the basic concepts and tools; there are other books that provide a good introduction to TDD.

Is This a Java Book?

We use the Java programming language throughout because it’s common enough that we expect our readers to be able at least to understand the examples. That said, the book is really about a set of techniques that are applicable to any object-oriented environment.

If you’re not using Java, there are equivalents of testing and mocking libraries we use (JUnit and jMock) in many other languages, including C#, Ruby, Python, Smalltalk, Objective-C, and (impressively) C++. There are even versions for more distant languages such as Scala. There are also other testing and mocking frameworks in Java.

Why Should You Listen to Us?

This book distills our experiences over a couple of decades, including nearly ten years of test-driven development. During that time, we have used TDD in a wide range of projects: large message-oriented enterprise-integration systems with an interactive web front-end backed by multiprocessor compute grids; tiny embedded systems that must run in tens of kilobytes of memory; free games used as advertising for business-critical systems; and back-end middleware and network services to highly interactive graphical desktop applications. In addition, we’ve written about and taught this material at events and companies across the world.

We’ve also benefited from the experience of our colleagues in the TDD community based in London. We’ve spent many hours during and after work having our ideas challenged and honed. We’re grateful for the opportunity to work with such lively (and argumentative) colleagues.

What Is in This Book?

The book has six parts:

Part I, “Introduction,” is a high-level introduction to test-driven development, mock objects, and object-oriented design within the context of a software development project. We also introduce some of the testing frameworks we use in the rest of the book. Even if you’re already familiar with TDD, we stilll recommend reading through Chapters 1 and 2 since they describe our approach to software development. If you’re familiar with JUnit and jMock, you might want to skip the rest of the introduction.

Part II, “The Process of Test-Driven Development,” describes the process of TDD, showing how to get started and how to keep development moving. We dig into the relationship between our test-driven approach and object-oriented programming, showing how the principles of the two techniques support each other. Finally, we discuss how to work with external code. This part describes the concepts, the next part puts them to work.

Part III, “A Worked Example,” is an extended example that gives a flavor of how we develop an object-oriented application in a test-driven manner. Along the way, we discuss the trade-offs and motivations for the decisions we take. We’ve made this quite a long example, because we want to show how some features of TDD become more significant as the code starts to scale up.

Part IV, “Sustainable Test-Driven Development,” describes some practices that keep a system maintainable. We’re very careful these days about keeping a codebase clean and expressive, because we’ve learned over the years the costs of letting things slip. This part describes some of the practices we’ve adopted and explains why we do them.

Part V, “Advanced Topics,” looks at areas where TDD is more difficult: complex test data, persistence, and concurrency. We show how we deal with these issues and how this affects the design of the code and tests.

Finally, the appendices include some supporting material on jMock and Hamcrest.

What Is Not in This Book?

This is a technical book. We’ve left out all the other topics that make a project succeed, such as team organization, requirements management, and product design. Adopting an incremental test-driven approach to development obviously has a close relationship with how a project is run. TDD enables some new activities, such as frequent delivery, and it can be crippled by organizational circumstances, such as an early design freeze or team stakeholders that don’t communicate. Again, there are plenty of other books to cover these topics.

Acknowledgments

The authors would like to thank everyone who provided their support and feedback during the writing of this book. Kent Beck and Greg Doench commissioned it in the first place, and Dmitry Kirsanov and Alina Kirsanova (with great patience) polished up the rough edges and turned it into print.

A great many people helped us by taking the trouble to read and review drafts, or just providing support and encouragement: Romilly Cocking, Jamie Dobson, Michael Feathers, Martin Fowler, Naresh Jain, Pete Keller, Tim Mackinnon, Duncan McGregor, Ivan Moore, Farshad Nayeri, Isaiah Perumalla, David Peterson, Nick Pomfret, J. B. Rainsberger, James Richardson, Lauren Schmitt, Douglas Squirrel, The Silicon Valley Patterns Group, Vladimir Trofimov, Daniel Wellman, and Matt Wynne.

Thanks to Dave Denton, Jonathan “Buck” Rogers, and Jim Kuo for modeling duties.

This book and the techniques we describe within it would not have existed without the Extreme Tuesday Club (XTC), a regular informal meet-up in London for people interested in agile, extreme programming and test-driven development. We are deeply grateful to all the people with whom we shared experiences, techniques, lessons learned, and rounds.

About the Authors

Steve Freeman

Steve Freeman is an independent consultant specializing in Agile software development (http://www.m3p.co.uk). He was joint winner, with Nat Pryce, of the 2006 Agile Alliance Gordon Pask award. A founding member of the London Extreme Tuesday Club, he was chair of the first London XP Day and is a frequent organizer and presenter at international conferences. Steve has worked in a wide variety of organizations, from developing shrink-wrap software for IBM to prototyping for major research labs. Steve has a PhD from Cambridge University, and degrees in statistics and music. Steve is based in London, UK.

Nat Pryce

After completing his PhD at Imperial College, Nat Pryce joined the dot-com boom just in time to watch it bust. Since then he has worked as a programmer, architect, trainer, and consultant in a variety of industries, including sports reportage, marketing communications, retail, telecoms, and finance. He has also worked on academic research projects and does occasional university teaching. An early adopter of XP, he has written or contributed to several open source libraries that support TDD and was one of the founding organizers of the London XP Day conference. He also regularly presents at international conferences. Nat is based in London, UK.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.188.218.226