scrum and hyper-productivity object mentor, inc. copyright 1998-2007 by object mentor, inc all...

147
Scrum and Hyper-productivity Object Mentor, Inc. Copyright 1998-2007 by Object Mentor, Inc All Rights Reserved fitnesse.org www.objectmentor.com www.junit.o rg Robert C. Martin

Upload: millicent-newton

Post on 11-Jan-2016

215 views

Category:

Documents


2 download

TRANSCRIPT

Page 1: Scrum and Hyper-productivity Object Mentor, Inc. Copyright  1998-2007 by Object Mentor, Inc All Rights Reserved fitnesse.org

Scrumand

Hyper-productivity

Object Mentor, Inc.

Copyright 1998-2007 by Object Mentor, IncAll Rights Reserved

fitnesse.org

www.objectmentor.com

www.junit.org

Robert C. Martin

Page 2: Scrum and Hyper-productivity Object Mentor, Inc. Copyright  1998-2007 by Object Mentor, Inc All Rights Reserved fitnesse.org

2

The inevitable trade-off.

Good (Quality)

Fast (Time to Market)

Cheap (Cost Effectiveness)

Done

Pick any three…

Page 3: Scrum and Hyper-productivity Object Mentor, Inc. Copyright  1998-2007 by Object Mentor, Inc All Rights Reserved fitnesse.org

3

Finding the optimum solution.

We need to manage the project to the best possible outcome.

An outcome that maximizes all four qualities.

To do this, we need:

Data.

Page 4: Scrum and Hyper-productivity Object Mentor, Inc. Copyright  1998-2007 by Object Mentor, Inc All Rights Reserved fitnesse.org

4

Wouldn’t this be great?

Velocity

0

10

20

30

40

50

60

1/20/20031/27/20032/3/20032/10/20032/17/20032/24/20033/3/20033/10/2003

Story Points

Page 5: Scrum and Hyper-productivity Object Mentor, Inc. Copyright  1998-2007 by Object Mentor, Inc All Rights Reserved fitnesse.org

5

…and this…

Story Points Remaining

0

100

200

300

400

500

600

1/20/20031/27/20032/3/20032/10/20032/17/20032/24/20033/3/20033/10/2003

Story Points

Page 6: Scrum and Hyper-productivity Object Mentor, Inc. Copyright  1998-2007 by Object Mentor, Inc All Rights Reserved fitnesse.org

6

If we had these two charts on the wall…

Story Points Remaining

0

100

200

300

400

500

600

1/20/20031/27/20032/3/20032/10/20032/17/20032/24/20033/3/20033/10/2003

Story Points

Velocity

0

10

20

30

40

50

60

1/20/20031/27/20032/3/20032/10/20032/17/20032/24/20033/3/20033/10/2003

Story Points

Then managers could just look at them to seeThe status of the project.

Page 7: Scrum and Hyper-productivity Object Mentor, Inc. Copyright  1998-2007 by Object Mentor, Inc All Rights Reserved fitnesse.org

7

What is the first thing

known about a project?

The Management Paradox

Page 8: Scrum and Hyper-productivity Object Mentor, Inc. Copyright  1998-2007 by Object Mentor, Inc All Rights Reserved fitnesse.org

8

! !

! !

Page 9: Scrum and Hyper-productivity Object Mentor, Inc. Copyright  1998-2007 by Object Mentor, Inc All Rights Reserved fitnesse.org

9

The Delivery Date is Frozen

Page 10: Scrum and Hyper-productivity Object Mentor, Inc. Copyright  1998-2007 by Object Mentor, Inc All Rights Reserved fitnesse.org

10

The

Spec

V1

The

Spec

V2

The

Spec

V3

The

Spec

V3

The

Spec

VN.1

The

Spec

VN.2

The Spec is Never Frozen

Page 11: Scrum and Hyper-productivity Object Mentor, Inc. Copyright  1998-2007 by Object Mentor, Inc All Rights Reserved fitnesse.org

11

Analysis

Design

Implementation

DFDERD

DDST

1 May 1 Nov1 Jul 1 Sep

The Waterfall Model

Managing the Development of Large Software SystemsDr. Winston W. Royce — 1970

Page 12: Scrum and Hyper-productivity Object Mentor, Inc. Copyright  1998-2007 by Object Mentor, Inc All Rights Reserved fitnesse.org

12

Royce’s actual diagram.

Page 13: Scrum and Hyper-productivity Object Mentor, Inc. Copyright  1998-2007 by Object Mentor, Inc All Rights Reserved fitnesse.org

13

Royce’s Observation

Page 14: Scrum and Hyper-productivity Object Mentor, Inc. Copyright  1998-2007 by Object Mentor, Inc All Rights Reserved fitnesse.org

14

Royce’s Conclusion

Page 15: Scrum and Hyper-productivity Object Mentor, Inc. Copyright  1998-2007 by Object Mentor, Inc All Rights Reserved fitnesse.org

15

Analysis

Design

Implementation

DFDERD

DDST

1 May 1 Nov1 Jul 1 Sep

Let’s go to a meeting.

Page 16: Scrum and Hyper-productivity Object Mentor, Inc. Copyright  1998-2007 by Object Mentor, Inc All Rights Reserved fitnesse.org

16

Iterative Development.

Exploration

Slices cut across all sub-systems

UI

Comms

ControlSome UI, Comms, and

Control for

some behavior

Data is generated and used to calibrate the plan

Page 17: Scrum and Hyper-productivity Object Mentor, Inc. Copyright  1998-2007 by Object Mentor, Inc All Rights Reserved fitnesse.org

17

Calculate the Date.

High level analysis and Design

Slices cut across all sub-systems

The Calculated Date

. . . . . . . . [ ]

Page 18: Scrum and Hyper-productivity Object Mentor, Inc. Copyright  1998-2007 by Object Mentor, Inc All Rights Reserved fitnesse.org

18

More data shrinks the error bars.

High level analysis and Design

Slices cut across all sub-systems

The Calculated Date

. . . . . . . . [ ]

Page 19: Scrum and Hyper-productivity Object Mentor, Inc. Copyright  1998-2007 by Object Mentor, Inc All Rights Reserved fitnesse.org

19

But when we have data…

Story Points Remaining

0

100

200

300

400

500

600

1/20/20031/27/20032/3/20032/10/20032/17/20032/24/20033/3/20033/10/2003

Story Points

Velocity

0

10

20

30

40

50

60

1/20/20031/27/20032/3/20032/10/20032/17/20032/24/20033/3/20033/10/2003

Story Points

Managers can…. manage.

Page 20: Scrum and Hyper-productivity Object Mentor, Inc. Copyright  1998-2007 by Object Mentor, Inc All Rights Reserved fitnesse.org

20

The control knobs of project mgt.

Schedule

Quality

Staff Scope

Page 21: Scrum and Hyper-productivity Object Mentor, Inc. Copyright  1998-2007 by Object Mentor, Inc All Rights Reserved fitnesse.org

21

SCRUM

Small Releases

WholeTeam

PlanningGame

DailyScrum

Page 22: Scrum and Hyper-productivity Object Mentor, Inc. Copyright  1998-2007 by Object Mentor, Inc All Rights Reserved fitnesse.org

22

This can lead to a Mess.

Messy Code is:rigid

fragile

not reusable

has high viscosity

Page 23: Scrum and Hyper-productivity Object Mentor, Inc. Copyright  1998-2007 by Object Mentor, Inc All Rights Reserved fitnesse.org

23

Rigidity

The impact of a change cannot be predictedIf not predicted, it cannot be estimatedTime and cost cannot be quantifiedManagers become reluctant to authorize changeOfficial Rigidity for “Roach Motel” modules

Rigidity is the inability to be changed

Page 24: Scrum and Hyper-productivity Object Mentor, Inc. Copyright  1998-2007 by Object Mentor, Inc All Rights Reserved fitnesse.org

24

Fragility

A single change requires a cascade of subsequent changesNew errors appear in areas that seem unconnected to the changed areasQuality is unpredictable.The development team loses credibility

Software changes seem to exhibit non-local effects

Page 25: Scrum and Hyper-productivity Object Mentor, Inc. Copyright  1998-2007 by Object Mentor, Inc All Rights Reserved fitnesse.org

25

Immobility

Desirable parts of the design are dependent upon undesirable partsThe work and risk of extracting the desirable part may exceed the cost of redeveloping from scratch.

Page 26: Scrum and Hyper-productivity Object Mentor, Inc. Copyright  1998-2007 by Object Mentor, Inc All Rights Reserved fitnesse.org

26

Viscosity

When the “right changes” are much more difficult than hacking, the viscosity of the system is high.

Over time, it will become increasingly difficult to continue developing the product.

Viscosity is resistance to fluid motion.

Page 27: Scrum and Hyper-productivity Object Mentor, Inc. Copyright  1998-2007 by Object Mentor, Inc All Rights Reserved fitnesse.org

27

What to do?

A good SCRUM team solves this problemBy adopting corrective disciplines.

What are those disciplines?

Page 28: Scrum and Hyper-productivity Object Mentor, Inc. Copyright  1998-2007 by Object Mentor, Inc All Rights Reserved fitnesse.org

28

Hyper-productive SCRUM

Metaphor

CollectiveOwnership

SustainablePace

ContinuousIntegration

Small Releases

Acceptance Tests

WholeTeam

PlanningGame

SimpleDesign

Pairing

Test Driven Development

Refactoring

Daily Scrum

Page 29: Scrum and Hyper-productivity Object Mentor, Inc. Copyright  1998-2007 by Object Mentor, Inc All Rights Reserved fitnesse.org

29

The Three Laws of TDD

You cannot write any production code until you have written a failing unit test.

You cannot write more of a unit test than is sufficient to fail.

You cannot write more production code than is sufficient to pass the failing test.

Page 30: Scrum and Hyper-productivity Object Mentor, Inc. Copyright  1998-2007 by Object Mentor, Inc All Rights Reserved fitnesse.org

30

The Litany of TDD Benefits

30 Second cycle time means less debugging.

A bevy of tests keeps the code flexible

The tests are design documents

Testable code is decoupled code.

Page 31: Scrum and Hyper-productivity Object Mentor, Inc. Copyright  1998-2007 by Object Mentor, Inc All Rights Reserved fitnesse.org

User Stories

Page 32: Scrum and Hyper-productivity Object Mentor, Inc. Copyright  1998-2007 by Object Mentor, Inc All Rights Reserved fitnesse.org

32

Stories

Name of a feature, or short description

Brief specifications of customer requirementsIs a token for a conversation

Owned by the customer

A good user story criteriaHas business value

Is estimable

Is testable

Return Car

Page 33: Scrum and Hyper-productivity Object Mentor, Inc. Copyright  1998-2007 by Object Mentor, Inc All Rights Reserved fitnesse.org

33

Story EstimationTeam assigns a estimate or price to each story

Estimates are in dimensionless but proportional units

A 2 takes twice as much effort as a 1

Customer uses price to juggle priorities and acquire resources

Unknowns can be eliminated through use of spikes, a research story

Page 34: Scrum and Hyper-productivity Object Mentor, Inc. Copyright  1998-2007 by Object Mentor, Inc All Rights Reserved fitnesse.org

34

User Stories Define the Project Backlog

Page 35: Scrum and Hyper-productivity Object Mentor, Inc. Copyright  1998-2007 by Object Mentor, Inc All Rights Reserved fitnesse.org

Agile Planning

User Stories

Release Planning

Iteration Planning

Page 36: Scrum and Hyper-productivity Object Mentor, Inc. Copyright  1998-2007 by Object Mentor, Inc All Rights Reserved fitnesse.org

36

The Purpose of Planning

It is more important to work on the most valuable things first than to predict the future.

• Even the best plans must be continually refined• Requires continuous and meaningful feedback

Page 37: Scrum and Hyper-productivity Object Mentor, Inc. Copyright  1998-2007 by Object Mentor, Inc All Rights Reserved fitnesse.org

37

Object Mentor’s Third Law ofAgile Development

“In preparing for battle I have always found that plans are useless, but

planning isindispensable. ”

Dwight David Eisenhower

Page 38: Scrum and Hyper-productivity Object Mentor, Inc. Copyright  1998-2007 by Object Mentor, Inc All Rights Reserved fitnesse.org

38

Exploration

AttendeesWhole team

InputProduct VisionInitial Story List (verbal)Critical dates

Output – on Flip Chart SheetsDeck of initial stories.Stakeholder IdentificationCustomer Team IdentificationArchitectural VisionInitial EstimatesVelocity guestimate

Page 39: Scrum and Hyper-productivity Object Mentor, Inc. Copyright  1998-2007 by Object Mentor, Inc All Rights Reserved fitnesse.org

39

Release Planning

AttendeesWhole team (as appropriate)

InputsStack of estimated stories

Team Velocity

Critical dates or initial release functionality

OutputsRelease plan – series of iterations, with significant dates

1 2 3 4 5 6 7

Page 40: Scrum and Hyper-productivity Object Mentor, Inc. Copyright  1998-2007 by Object Mentor, Inc All Rights Reserved fitnesse.org

40

Release Planning

The 4-way Decision.

ImportantExpensive

ImportantCheap

UnimportantExpensive

UnimportantCheap

Page 41: Scrum and Hyper-productivity Object Mentor, Inc. Copyright  1998-2007 by Object Mentor, Inc All Rights Reserved fitnesse.org

41

USER

STORY

USER

STORY

USER

STORY

Managing Scope

USER

STORY

USER

STORY

USER

STORY

USER

STORY

USER

STORY

USER

STORY

USER

STORY

USER

STORY

USER

STORYUSER

STORY

USER

STORY

USER

STORYUSER

STORY

USER

STORY

USER

STORYUSER

STORY

USER

STORY

USER

STORYUSER

STORY

USER

STORY

USER

STORYUSER

STORY

USER

STORY

USER

STORYUSER

STORY

USER

STORY

USER

STORYUSER

STORY

USER

STORY

USER

STORY

GetHigher Business Value

Lower Business Value

Source: Object Mentor Training

Don’t get (yet)

Page 42: Scrum and Hyper-productivity Object Mentor, Inc. Copyright  1998-2007 by Object Mentor, Inc All Rights Reserved fitnesse.org

42

Release Planning Summary

Customers write stories

Programmers estimate cost of stories

Customers prioritize based on business value and estimated costs

Release velocity: number of story points completed

Yesterday’s weather

Page 43: Scrum and Hyper-productivity Object Mentor, Inc. Copyright  1998-2007 by Object Mentor, Inc All Rights Reserved fitnesse.org

43

Release Plan

1 2 3 4 5 6 7

Release 1 Release 2

Page 44: Scrum and Hyper-productivity Object Mentor, Inc. Copyright  1998-2007 by Object Mentor, Inc All Rights Reserved fitnesse.org

44

Iteration Planning

Monday Morning:Confirm the stories for the iteration

Revise estimates based on new information For each story

Write story on top of flip chart pageReview acceptance testsBreak story into engineering tasksDo quick design session as neededSign up.

Page 45: Scrum and Hyper-productivity Object Mentor, Inc. Copyright  1998-2007 by Object Mentor, Inc All Rights Reserved fitnesse.org

45

Iteration Planning Summary

Developers break stories into tasks

Developers sign up for stories.

Customers may need to change, split, merge stories to fit iteration

Once in the iteration, the stories are fixed

Iteration velocity: number of story points completed

Never extend the iteration date

Page 46: Scrum and Hyper-productivity Object Mentor, Inc. Copyright  1998-2007 by Object Mentor, Inc All Rights Reserved fitnesse.org

46

Iteration Tracking Bulletin Board

Selected AcceptedStarted Done?

Page 47: Scrum and Hyper-productivity Object Mentor, Inc. Copyright  1998-2007 by Object Mentor, Inc All Rights Reserved fitnesse.org

47

Iteration Tracking Bulletin Board

Selected AcceptedStarted Done?

Page 48: Scrum and Hyper-productivity Object Mentor, Inc. Copyright  1998-2007 by Object Mentor, Inc All Rights Reserved fitnesse.org

48

How do you know a story is done?

1 2 3 4 5 6 7

Working CodePassing Tests

Page 49: Scrum and Hyper-productivity Object Mentor, Inc. Copyright  1998-2007 by Object Mentor, Inc All Rights Reserved fitnesse.org

Writing AutomatedAcceptance Tests

Object Mentor, Inc.

Copyright 1998-2001 by Object Mentor, IncAll Rights Reserved

Page 50: Scrum and Hyper-productivity Object Mentor, Inc. Copyright  1998-2007 by Object Mentor, Inc All Rights Reserved fitnesse.org

The Role of QA in an Agile Project

Page 51: Scrum and Hyper-productivity Object Mentor, Inc. Copyright  1998-2007 by Object Mentor, Inc All Rights Reserved fitnesse.org

51

The Traditional schedule for Quality.

Waiting at the sphincter muscle.

Analysis

Design

Implementation

1 May 1 Nov1 Jul 1 Sep

Test

Page 52: Scrum and Hyper-productivity Object Mentor, Inc. Copyright  1998-2007 by Object Mentor, Inc All Rights Reserved fitnesse.org

52

When Quality comes at the end.

It is under the most pressure.

It has the least flexibility.

It is a high stress tedious job.

It is error prone.

Quality cannot be tested in.

Page 53: Scrum and Hyper-productivity Object Mentor, Inc. Copyright  1998-2007 by Object Mentor, Inc All Rights Reserved fitnesse.org

The Agile View:

Quality is a specification role…

…not a verification role!

Page 54: Scrum and Hyper-productivity Object Mentor, Inc. Copyright  1998-2007 by Object Mentor, Inc All Rights Reserved fitnesse.org

A feature is not specified…

Until it’s acceptance test is written.

Page 55: Scrum and Hyper-productivity Object Mentor, Inc. Copyright  1998-2007 by Object Mentor, Inc All Rights Reserved fitnesse.org

55

Who Writes Acceptance Tests?

Business AnalystsHappy path.

QA Test Writers, and TestersCorner and boundary cases.

Try to break it.

Page 56: Scrum and Hyper-productivity Object Mentor, Inc. Copyright  1998-2007 by Object Mentor, Inc All Rights Reserved fitnesse.org

56

Acceptance Tests Are…

Automated.

written in a very high level language.

executed frequently.

written by the stakeholders.

Page 57: Scrum and Hyper-productivity Object Mentor, Inc. Copyright  1998-2007 by Object Mentor, Inc All Rights Reserved fitnesse.org

57

Imagine you have a button to press that would tell you if the system worked

How often would you press it?

Page 58: Scrum and Hyper-productivity Object Mentor, Inc. Copyright  1998-2007 by Object Mentor, Inc All Rights Reserved fitnesse.org

58

It becomes a conditioned response.

Page 59: Scrum and Hyper-productivity Object Mentor, Inc. Copyright  1998-2007 by Object Mentor, Inc All Rights Reserved fitnesse.org

When is the best time to write Automated Acceptance Tests?

Page 60: Scrum and Hyper-productivity Object Mentor, Inc. Copyright  1998-2007 by Object Mentor, Inc All Rights Reserved fitnesse.org

60

At the start of each iteration.

Exploration

Slices cut across all sub-systems

Test

Page 61: Scrum and Hyper-productivity Object Mentor, Inc. Copyright  1998-2007 by Object Mentor, Inc All Rights Reserved fitnesse.org

61

Tests specify each iteration.

Iteration

AcceptanceTests

Defines done-ness.

Page 62: Scrum and Hyper-productivity Object Mentor, Inc. Copyright  1998-2007 by Object Mentor, Inc All Rights Reserved fitnesse.org

62

Tests specify each iteration.

Iteration

AcceptanceTests

Defines done-ness.

Page 63: Scrum and Hyper-productivity Object Mentor, Inc. Copyright  1998-2007 by Object Mentor, Inc All Rights Reserved fitnesse.org

How do you know a feature is done?

Page 64: Scrum and Hyper-productivity Object Mentor, Inc. Copyright  1998-2007 by Object Mentor, Inc All Rights Reserved fitnesse.org

A feature is not done…

Until all it’s acceptance tests pass.

Page 65: Scrum and Hyper-productivity Object Mentor, Inc. Copyright  1998-2007 by Object Mentor, Inc All Rights Reserved fitnesse.org

65

Knowing when a feature is done allows...

Story Points Remaining

0

100

200

300

400

500

600

1/20/20031/27/20032/3/20032/10/20032/17/20032/24/20033/3/20033/10/2003

Story Points

Velocity

0

10

20

30

40

50

60

1/20/20031/27/20032/3/20032/10/20032/17/20032/24/20033/3/20033/10/2003

Story Points

These features have passed their AutomatedAcceptance Tests.

Page 66: Scrum and Hyper-productivity Object Mentor, Inc. Copyright  1998-2007 by Object Mentor, Inc All Rights Reserved fitnesse.org

What do they look like?

Page 67: Scrum and Hyper-productivity Object Mentor, Inc. Copyright  1998-2007 by Object Mentor, Inc All Rights Reserved fitnesse.org

A Simple Example

Page 68: Scrum and Hyper-productivity Object Mentor, Inc. Copyright  1998-2007 by Object Mentor, Inc All Rights Reserved fitnesse.org

The result.

Page 69: Scrum and Hyper-productivity Object Mentor, Inc. Copyright  1998-2007 by Object Mentor, Inc All Rights Reserved fitnesse.org

69

When is the best time to write AATs?

Astute test managers Talk to the stakeholders days before each iteration.

Write initial acceptance tests for the features they plan to schedule.

Elaborate those acceptance tests once scheduled.

Page 70: Scrum and Hyper-productivity Object Mentor, Inc. Copyright  1998-2007 by Object Mentor, Inc All Rights Reserved fitnesse.org

70

When is the best time to run them?

Continuously.

At every check-in.

No change is allowed to break any passing tests.

Continuous Integration.

Page 71: Scrum and Hyper-productivity Object Mentor, Inc. Copyright  1998-2007 by Object Mentor, Inc All Rights Reserved fitnesse.org

71

Who runs them?

Developers.

Testers.

Managers.

Stakeholders.

…They are run automatically.

…Results are displayed on the wall.

Page 72: Scrum and Hyper-productivity Object Mentor, Inc. Copyright  1998-2007 by Object Mentor, Inc All Rights Reserved fitnesse.org

72

This keeps the data accurate…

Story Points Remaining

0

100

200

300

400

500

600

1/20/20031/27/20032/3/20032/10/20032/17/20032/24/20033/3/20033/10/2003

Story Points

Velocity

0

10

20

30

40

50

60

1/20/20031/27/20032/3/20032/10/20032/17/20032/24/20033/3/20033/10/2003

Story Points

…and actionable.

Page 73: Scrum and Hyper-productivity Object Mentor, Inc. Copyright  1998-2007 by Object Mentor, Inc All Rights Reserved fitnesse.org

73

Evolution: Manual Tests

Used for lack of any better approachAre better than nothingTerribly InefficientIn a crunch they are not runUnfortunately still among the most commonly used approach

Page 74: Scrum and Hyper-productivity Object Mentor, Inc. Copyright  1998-2007 by Object Mentor, Inc All Rights Reserved fitnesse.org

74

Evolution: Ad Hoc Text-based

CSV or Tab delimited filesAllowed for automation of testsDoes not scale wellVery unconventionalEveryone used a different schemeNot very customer friendly

Page 75: Scrum and Hyper-productivity Object Mentor, Inc. Copyright  1998-2007 by Object Mentor, Inc All Rights Reserved fitnesse.org

75

Evolution: XML-based

Still automatedScalableVisions of frameworks beganXML introduces extra complexityNot customer friendly

Page 76: Scrum and Hyper-productivity Object Mentor, Inc. Copyright  1998-2007 by Object Mentor, Inc All Rights Reserved fitnesse.org

76

GUI Testers

Mercury

Robot

Canoo

WebRunnerEtc.

Page 77: Scrum and Hyper-productivity Object Mentor, Inc. Copyright  1998-2007 by Object Mentor, Inc All Rights Reserved fitnesse.org

77

Testing through GUI is a trap.

We have a client with 15,000 acceptance tests run through the GUI.

Old DOS based GUI.

Can’t update GUI because tests would fail.

Stuck!

Page 78: Scrum and Hyper-productivity Object Mentor, Inc. Copyright  1998-2007 by Object Mentor, Inc All Rights Reserved fitnesse.org

FitNesse

The solution we all agreed upon.

Page 79: Scrum and Hyper-productivity Object Mentor, Inc. Copyright  1998-2007 by Object Mentor, Inc All Rights Reserved fitnesse.org

79

Writing Requirements as Tests

Requirements are written with example tables.The tables are really tests.Writing tests as a table is an interesting paradigm

Some tests naturally fit into tablesSome tests require thought to put them in the form of a table

Page 80: Scrum and Hyper-productivity Object Mentor, Inc. Copyright  1998-2007 by Object Mentor, Inc All Rights Reserved fitnesse.org

80

The Mechanics

The first row of a FIT table is the title of the table.

This title is the name of something called a “fixture”.

Fixtures are simple programs written by the developers to connect the application to the data in the table.

Page 81: Scrum and Hyper-productivity Object Mentor, Inc. Copyright  1998-2007 by Object Mentor, Inc All Rights Reserved fitnesse.org

81

The MechanicsWhen you run a test the fixture gathers the data from the table and calls the appropriate functions in the application.

The fixture then gathers data from the application and compares them with entries in the table, turning them green or red.

Page 82: Scrum and Hyper-productivity Object Mentor, Inc. Copyright  1998-2007 by Object Mentor, Inc All Rights Reserved fitnesse.org

82

Acceptance Testing with Fit/FitNesse

The Application InterfaceUI

Fit Fixtures Fit/FitNesse

The ApplicationLogic

Page 83: Scrum and Hyper-productivity Object Mentor, Inc. Copyright  1998-2007 by Object Mentor, Inc All Rights Reserved fitnesse.org

The Test-Bus Imperative

Page 84: Scrum and Hyper-productivity Object Mentor, Inc. Copyright  1998-2007 by Object Mentor, Inc All Rights Reserved fitnesse.org

84

Many Industries build testability in.

Telecommunications

Manufacturing

Electronic Hardware

Page 85: Scrum and Hyper-productivity Object Mentor, Inc. Copyright  1998-2007 by Object Mentor, Inc All Rights Reserved fitnesse.org

85

But not the software industry.

Testability is almost always an afterthought

If it is thought of at all.

Page 86: Scrum and Hyper-productivity Object Mentor, Inc. Copyright  1998-2007 by Object Mentor, Inc All Rights Reserved fitnesse.org

86

Untestable Dependencies.

Network

Network

READY

Too often applications directly depend on external and third party resources.

Page 87: Scrum and Hyper-productivity Object Mentor, Inc. Copyright  1998-2007 by Object Mentor, Inc All Rights Reserved fitnesse.org

87

Dependency Management

Network

Network

READY

Interfaces isolate the system from external dependencies.

Page 88: Scrum and Hyper-productivity Object Mentor, Inc. Copyright  1998-2007 by Object Mentor, Inc All Rights Reserved fitnesse.org

88

Testability!

Tests andSimulations

Tests andSimulations

Tests andSimulations

Page 89: Scrum and Hyper-productivity Object Mentor, Inc. Copyright  1998-2007 by Object Mentor, Inc All Rights Reserved fitnesse.org

Measuring Project Status

Page 90: Scrum and Hyper-productivity Object Mentor, Inc. Copyright  1998-2007 by Object Mentor, Inc All Rights Reserved fitnesse.org

90

Project Management Tool

When done properly, Acceptance Tests produce valuable data.

0102030405060708090

100

1 3 5 7 9 11

Total AT'sFailing AT'sPassing AT's

Page 91: Scrum and Hyper-productivity Object Mentor, Inc. Copyright  1998-2007 by Object Mentor, Inc All Rights Reserved fitnesse.org

91

ATs keep the PM data accurate…

Story Points Remaining

0

100

200

300

400

500

600

1/20/20031/27/20032/3/20032/10/20032/17/20032/24/20033/3/20033/10/2003

Story Points

Velocity

0

10

20

30

40

50

60

1/20/20031/27/20032/3/20032/10/20032/17/20032/24/20033/3/20033/10/2003

Story Points

…and actionable.

Page 92: Scrum and Hyper-productivity Object Mentor, Inc. Copyright  1998-2007 by Object Mentor, Inc All Rights Reserved fitnesse.org

92

Iteration Management

Page 93: Scrum and Hyper-productivity Object Mentor, Inc. Copyright  1998-2007 by Object Mentor, Inc All Rights Reserved fitnesse.org

93

Agile Software Development Practices

Metaphor

CollectiveOwnership

SustainablePace

ContinuousIntegration

Small Releases

Acceptance Tests

CustomerCollaboration

Scrum

SimpleDesign

Pairing

Test Driven Development

Refactoring

Page 94: Scrum and Hyper-productivity Object Mentor, Inc. Copyright  1998-2007 by Object Mentor, Inc All Rights Reserved fitnesse.org

Bowling Game Kata

Copyright 2005 by Object Mentor, IncAll copies must retain this page unchanged.

Page 95: Scrum and Hyper-productivity Object Mentor, Inc. Copyright  1998-2007 by Object Mentor, Inc All Rights Reserved fitnesse.org

95

Scoring Bowling.

The game consists of 10 frames as shown above. In each frame the player hastwo opportunities to knock down 10 pins. The score for the frame is the totalnumber of pins knocked down, plus bonuses for strikes and spares.

A spare is when the player knocks down all 10 pins in two tries. The bonus forthat frame is the number of pins knocked down by the next roll. So in frame 3above, the score is 10 (the total number knocked down) plus a bonus of 5 (thenumber of pins knocked down on the next roll.)

A strike is when the player knocks down all 10 pins on his first try. The bonusfor that frame is the value of the next two balls rolled.

In the tenth frame a player who rolls a spare or strike is allowed to roll the extraballs to complete the frame. However no more than three balls can be rolled intenth frame.

Page 96: Scrum and Hyper-productivity Object Mentor, Inc. Copyright  1998-2007 by Object Mentor, Inc All Rights Reserved fitnesse.org

96

The Requirements.

+ roll(pins : int)+ score() : int

Game

Write a class named “Game” that has two methods

roll(pins : int) is called each time the player rolls a ball. The argument is the number of pins knocked down.

score() : int is called only at the very end of the game. It returns the total score for that game.

Page 97: Scrum and Hyper-productivity Object Mentor, Inc. Copyright  1998-2007 by Object Mentor, Inc All Rights Reserved fitnesse.org

97

A quick design session

+ roll(pins : int)+ score() : int

Game

Clearly we need the Game class.

Page 98: Scrum and Hyper-productivity Object Mentor, Inc. Copyright  1998-2007 by Object Mentor, Inc All Rights Reserved fitnesse.org

98

A quick design session

+ roll(pins : int)+ score() : int

Game Frame10

A game has 10 frames.

Page 99: Scrum and Hyper-productivity Object Mentor, Inc. Copyright  1998-2007 by Object Mentor, Inc All Rights Reserved fitnesse.org

99

A quick design session

+ roll(pins : int)+ score() : int

Game Frame

- pins : int

Roll10 1..2

A frame has 1 or two rolls.

Page 100: Scrum and Hyper-productivity Object Mentor, Inc. Copyright  1998-2007 by Object Mentor, Inc All Rights Reserved fitnesse.org

100

A quick design session

+ roll(pins : int)+ score() : int

Game Frame

Tenth Frame

- pins : int

Roll10 1..2

1

The tenth frame has two or three rolls.It is different from all the other frames.

Page 101: Scrum and Hyper-productivity Object Mentor, Inc. Copyright  1998-2007 by Object Mentor, Inc All Rights Reserved fitnesse.org

101

A quick design session

+ roll(pins : int)+ score() : int

Game

+ score() : int

Frame

Tenth Frame

- pins : int

Roll10 1..2

1The score function mustiterate through all theframes, and calculateall their scores.

Page 102: Scrum and Hyper-productivity Object Mentor, Inc. Copyright  1998-2007 by Object Mentor, Inc All Rights Reserved fitnesse.org

102

A quick design session

+ roll(pins : int)+ score() : int

Game

+ score() : int

Frame

Tenth Frame

- pins : int

Roll10 1..2

1

next frame The score for a spare or a strike depends on the frame’s successor

Page 103: Scrum and Hyper-productivity Object Mentor, Inc. Copyright  1998-2007 by Object Mentor, Inc All Rights Reserved fitnesse.org

103

Begin.

Create a project named BowlingGame

Create a unit test named BowlingGameTest

import junit.framework.TestCase;

public class BowlingGameTest extends TestCase {}

Page 104: Scrum and Hyper-productivity Object Mentor, Inc. Copyright  1998-2007 by Object Mentor, Inc All Rights Reserved fitnesse.org

104

Begin.

Create a project named BowlingGame

Create a unit test named BowlingGameTest

import junit.framework.TestCase;

public class BowlingGameTest extends TestCase {}

Execute this program and verify that you get the following error:

No tests found in BowlingGameTest

Page 105: Scrum and Hyper-productivity Object Mentor, Inc. Copyright  1998-2007 by Object Mentor, Inc All Rights Reserved fitnesse.org

105

The first test.import junit.framework.TestCase;

public class BowlingGameTest extends TestCase { public void testGutterGame() throws Exception { Game g = new Game(); }}

Page 106: Scrum and Hyper-productivity Object Mentor, Inc. Copyright  1998-2007 by Object Mentor, Inc All Rights Reserved fitnesse.org

106

The first test.import junit.framework.TestCase;

public class BowlingGameTest extends TestCase { public void testGutterGame() throws Exception { Game g = new Game(); }}

public class Game {}

Page 107: Scrum and Hyper-productivity Object Mentor, Inc. Copyright  1998-2007 by Object Mentor, Inc All Rights Reserved fitnesse.org

107

The first test.import junit.framework.TestCase;

public class BowlingGameTest extends TestCase { public void testGutterGame() throws Exception { Game g = new Game(); }}

public class Game {}

Page 108: Scrum and Hyper-productivity Object Mentor, Inc. Copyright  1998-2007 by Object Mentor, Inc All Rights Reserved fitnesse.org

108

The first test.import junit.framework.TestCase;

public class BowlingGameTest extends TestCase { public void testGutterGame() throws Exception { Game g = new Game(); for (int i=0; i<20; i++) g.roll(0); }}

public class Game {}

Page 109: Scrum and Hyper-productivity Object Mentor, Inc. Copyright  1998-2007 by Object Mentor, Inc All Rights Reserved fitnesse.org

109

The first test.import junit.framework.TestCase;

public class BowlingGameTest extends TestCase { public void testGutterGame() throws Exception { Game g = new Game(); for (int i=0; i<20; i++) g.roll(0); }}

public class Game { public void roll(int pins) { }}

Page 110: Scrum and Hyper-productivity Object Mentor, Inc. Copyright  1998-2007 by Object Mentor, Inc All Rights Reserved fitnesse.org

110

The first test.import junit.framework.TestCase;

public class BowlingGameTest extends TestCase { public void testGutterGame() throws Exception { Game g = new Game(); for (int i=0; i<20; i++) g.roll(0); assertEquals(0, g.score()); }}

public class Game { public void roll(int pins) { }}

Page 111: Scrum and Hyper-productivity Object Mentor, Inc. Copyright  1998-2007 by Object Mentor, Inc All Rights Reserved fitnesse.org

111

The first test.import junit.framework.TestCase;

public class BowlingGameTest extends TestCase { public void testGutterGame() throws Exception { Game g = new Game(); for (int i=0; i<20; i++) g.roll(0); assertEquals(0, g.score()); }}

public class Game { public void roll(int pins) { }

public int score() { return -1; }}

expected:<0> but was:<-1>

Page 112: Scrum and Hyper-productivity Object Mentor, Inc. Copyright  1998-2007 by Object Mentor, Inc All Rights Reserved fitnesse.org

112

The first test.import junit.framework.TestCase;

public class BowlingGameTest extends TestCase { public void testGutterGame() throws Exception { Game g = new Game(); for (int i=0; i<20; i++) g.roll(0); assertEquals(0, g.score()); }}

public class Game { public void roll(int pins) { }

public int score() { return 0; }}

Page 113: Scrum and Hyper-productivity Object Mentor, Inc. Copyright  1998-2007 by Object Mentor, Inc All Rights Reserved fitnesse.org

113

The Second test.import junit.framework.TestCase;

public class BowlingGameTest extends TestCase { public void testGutterGame() throws Exception { Game g = new Game(); for (int i = 0; i < 20; i++) g.roll(0); assertEquals(0, g.score()); }

public void testAllOnes() throws Exception { Game g = new Game(); for (int i = 0; i < 20; i++) g.roll(1); assertEquals(20, g.score()); }}

public class Game { public void roll(int pins) { }

public int score() { return 0; }}

Page 114: Scrum and Hyper-productivity Object Mentor, Inc. Copyright  1998-2007 by Object Mentor, Inc All Rights Reserved fitnesse.org

114

The Second test.import junit.framework.TestCase;

public class BowlingGameTest extends TestCase { public void testGutterGame() throws Exception { Game g = new Game(); for (int i = 0; i < 20; i++) g.roll(0); assertEquals(0, g.score()); }

public void testAllOnes() throws Exception { Game g = new Game(); for (int i = 0; i < 20; i++) g.roll(1); assertEquals(20, g.score()); }}

public class Game { public void roll(int pins) { }

public int score() { return 0; }}

- Game creation is duplicated- roll loop is duplicated

Page 115: Scrum and Hyper-productivity Object Mentor, Inc. Copyright  1998-2007 by Object Mentor, Inc All Rights Reserved fitnesse.org

115

The Second test.import junit.framework.TestCase;

public class BowlingGameTest extends TestCase { public void testGutterGame() throws Exception { Game g = new Game(); for (int i = 0; i < 20; i++) g.roll(0); assertEquals(0, g.score()); }

public void testAllOnes() throws Exception { Game g = new Game(); for (int i = 0; i < 20; i++) g.roll(1); assertEquals(20, g.score()); }}

public class Game { public void roll(int pins) { }

public int score() { return 0; }}

- Game creation is duplicated- roll loop is duplicated

expected:<20> but was:<0>

Page 116: Scrum and Hyper-productivity Object Mentor, Inc. Copyright  1998-2007 by Object Mentor, Inc All Rights Reserved fitnesse.org

116

The Second test.import junit.framework.TestCase;

public class BowlingGameTest extends TestCase { private Game g;

protected void setUp() throws Exception { g = new Game(); }

public void testGutterGame() throws Exception { for (int i = 0; i < 20; i++) g.roll(0); assertEquals(0, g.score()); }

public void testAllOnes() throws Exception { for (int i = 0; i < 20; i++) g.roll(1); assertEquals(20, g.score()); }}

public class Game { private int score = 0;

public void roll(int pins) { score += pins; }

public int score() { return score; }}

- roll loop is duplicated

Page 117: Scrum and Hyper-productivity Object Mentor, Inc. Copyright  1998-2007 by Object Mentor, Inc All Rights Reserved fitnesse.org

117

The Second test.import junit.framework.TestCase;

public class BowlingGameTest extends TestCase { private Game g;

protected void setUp() throws Exception { g = new Game(); }

public void testGutterGame() throws Exception { int n = 20; int pins = 0; for (int i = 0; i < n; i++) { g.roll(pins); } assertEquals(0, g.score()); }

public void testAllOnes() throws Exception { for (int i = 0; i < 20; i++) g.roll(1); assertEquals(20, g.score()); }}

public class Game { private int score = 0;

public void roll(int pins) { score += pins; }

public int score() { return score; }}

- roll loop is duplicated

Page 118: Scrum and Hyper-productivity Object Mentor, Inc. Copyright  1998-2007 by Object Mentor, Inc All Rights Reserved fitnesse.org

118

The Second test.import junit.framework.TestCase;

public class BowlingGameTest extends TestCase { private Game g;

protected void setUp() throws Exception { g = new Game(); }

public void testGutterGame() throws Exception { int n = 20; int pins = 0; rollMany(n, pins); assertEquals(0, g.score()); }

private void rollMany(int n, int pins) { for (int i = 0; i < n; i++) g.roll(pins); }

public void testAllOnes() throws Exception { for (int i = 0; i < 20; i++) g.roll(1); assertEquals(20, g.score()); }}

public class Game { private int score = 0;

public void roll(int pins) { score += pins; }

public int score() { return score; }}

- roll loop is duplicated

Page 119: Scrum and Hyper-productivity Object Mentor, Inc. Copyright  1998-2007 by Object Mentor, Inc All Rights Reserved fitnesse.org

119

The Second test.import junit.framework.TestCase;

public class BowlingGameTest extends TestCase { private Game g;

protected void setUp() throws Exception { g = new Game(); }

public void testGutterGame() throws Exception { rollMany(20, 0); assertEquals(0, g.score()); }

private void rollMany(int n, int pins) { for (int i = 0; i < n; i++) g.roll(pins); }

public void testAllOnes() throws Exception { for (int i = 0; i < 20; i++) g.roll(1); assertEquals(20, g.score()); }}

public class Game { private int score = 0;

public void roll(int pins) { score += pins; }

public int score() { return score; }}

- roll loop is duplicated

Page 120: Scrum and Hyper-productivity Object Mentor, Inc. Copyright  1998-2007 by Object Mentor, Inc All Rights Reserved fitnesse.org

120

The Second test.import junit.framework.TestCase;

public class BowlingGameTest extends TestCase { private Game g;

protected void setUp() throws Exception { g = new Game(); }

public void testGutterGame() throws Exception { rollMany(20, 0); assertEquals(0, g.score()); }

private void rollMany(int n, int pins) { for (int i = 0; i < n; i++) g.roll(pins); }

public void testAllOnes() throws Exception { rollMany(20,1); assertEquals(20, g.score()); }}

public class Game { private int score = 0;

public void roll(int pins) { score += pins; }

public int score() { return score; }}

- roll loop is duplicated

Page 121: Scrum and Hyper-productivity Object Mentor, Inc. Copyright  1998-2007 by Object Mentor, Inc All Rights Reserved fitnesse.org

121

The Second test.import junit.framework.TestCase;

public class BowlingGameTest extends TestCase { private Game g;

protected void setUp() throws Exception { g = new Game(); } private void rollMany(int n, int pins) { for (int i = 0; i < n; i++) g.roll(pins); } public void testGutterGame() throws Exception { rollMany(20, 0); assertEquals(0, g.score()); }

public void testAllOnes() throws Exception { rollMany(20,1); assertEquals(20, g.score()); }}

public class Game { private int score = 0;

public void roll(int pins) { score += pins; }

public int score() { return score; }}

Page 122: Scrum and Hyper-productivity Object Mentor, Inc. Copyright  1998-2007 by Object Mentor, Inc All Rights Reserved fitnesse.org

122

The Third test.import junit.framework.TestCase;

public class BowlingGameTest extends TestCase { private Game g;

protected void setUp() throws Exception { g = new Game(); }

private void rollMany(int n, int pins) { for (int i = 0; i < n; i++) g.roll(pins); }

public void testGutterGame() throws Exception { rollMany(20, 0); assertEquals(0, g.score()); }

public void testAllOnes() throws Exception { rollMany(20,1); assertEquals(20, g.score()); }

public void testOneSpare() throws Exception { g.roll(5); g.roll(5); // spare g.roll(3); rollMany(17,0); assertEquals(16,g.score()); }}

public class Game { private int score = 0;

public void roll(int pins) { score += pins; }

public int score() { return score; }}

- ugly comment in test.

Page 123: Scrum and Hyper-productivity Object Mentor, Inc. Copyright  1998-2007 by Object Mentor, Inc All Rights Reserved fitnesse.org

123

The Third test.import junit.framework.TestCase;

public class BowlingGameTest extends TestCase { private Game g;

protected void setUp() throws Exception { g = new Game(); }

private void rollMany(int n, int pins) { for (int i = 0; i < n; i++) g.roll(pins); }

public void testGutterGame() throws Exception { rollMany(20, 0); assertEquals(0, g.score()); }

public void testAllOnes() throws Exception { rollMany(20,1); assertEquals(20, g.score()); }

public void testOneSpare() throws Exception { g.roll(5); g.roll(5); // spare g.roll(3); rollMany(17,0); assertEquals(16,g.score()); }}

public class Game { private int score = 0;

public void roll(int pins) { score += pins; }

public int score() { return score; }}

- ugly comment in test.

expected:<16> but was:<13>

Page 124: Scrum and Hyper-productivity Object Mentor, Inc. Copyright  1998-2007 by Object Mentor, Inc All Rights Reserved fitnesse.org

124

The Third test.import junit.framework.TestCase;

public class BowlingGameTest extends TestCase { private Game g;

protected void setUp() throws Exception { g = new Game(); }

private void rollMany(int n, int pins) { for (int i = 0; i < n; i++) g.roll(pins); }

public void testGutterGame() throws Exception { rollMany(20, 0); assertEquals(0, g.score()); }

public void testAllOnes() throws Exception { rollMany(20,1); assertEquals(20, g.score()); }

public void testOneSpare() throws Exception { g.roll(5); g.roll(5); // spare g.roll(3); rollMany(17,0); assertEquals(16,g.score()); }}

public class Game { private int score = 0;

public void roll(int pins) { score += pins; }

public int score() { return score; }}

- ugly comment in test.

tempted to use flag to remember previous roll. So design must be wrong.

Page 125: Scrum and Hyper-productivity Object Mentor, Inc. Copyright  1998-2007 by Object Mentor, Inc All Rights Reserved fitnesse.org

125

The Third test.import junit.framework.TestCase;

public class BowlingGameTest extends TestCase { private Game g;

protected void setUp() throws Exception { g = new Game(); }

private void rollMany(int n, int pins) { for (int i = 0; i < n; i++) g.roll(pins); }

public void testGutterGame() throws Exception { rollMany(20, 0); assertEquals(0, g.score()); }

public void testAllOnes() throws Exception { rollMany(20,1); assertEquals(20, g.score()); }

public void testOneSpare() throws Exception { g.roll(5); g.roll(5); // spare g.roll(3); rollMany(17,0); assertEquals(16,g.score()); }}

public class Game { private int score = 0;

public void roll(int pins) { score += pins; }

public int score() { return score; }}

- ugly comment in test.

roll() calculates score, but name does not imply that.

score() does not calculate score, but name implies that it does.

Design is wrong. Responsibilities are misplaced.

Page 126: Scrum and Hyper-productivity Object Mentor, Inc. Copyright  1998-2007 by Object Mentor, Inc All Rights Reserved fitnesse.org

126

The Third test.import junit.framework.TestCase;

public class BowlingGameTest extends TestCase { private Game g;

protected void setUp() throws Exception { g = new Game(); }

private void rollMany(int n, int pins) { for (int i = 0; i < n; i++) g.roll(pins); }

public void testGutterGame() throws Exception { rollMany(20, 0); assertEquals(0, g.score()); }

public void testAllOnes() throws Exception { rollMany(20,1); assertEquals(20, g.score()); }

// public void testOneSpare() throws Exception {// g.roll(5);// g.roll(5); // spare// g.roll(3);// rollMany(17,0);// assertEquals(16,g.score());// }}

public class Game { private int score = 0;

public void roll(int pins) { score += pins; }

public int score() { return score; }}

- ugly comment in test.

Page 127: Scrum and Hyper-productivity Object Mentor, Inc. Copyright  1998-2007 by Object Mentor, Inc All Rights Reserved fitnesse.org

127

The Third test.import junit.framework.TestCase;

public class BowlingGameTest extends TestCase { private Game g;

protected void setUp() throws Exception { g = new Game(); }

private void rollMany(int n, int pins) { for (int i = 0; i < n; i++) g.roll(pins); }

public void testGutterGame() throws Exception { rollMany(20, 0); assertEquals(0, g.score()); }

public void testAllOnes() throws Exception { rollMany(20,1); assertEquals(20, g.score()); }

// public void testOneSpare() throws Exception {// g.roll(5);// g.roll(5); // spare// g.roll(3);// rollMany(17,0);// assertEquals(16,g.score());// }}

public class Game { private int score = 0; private int rolls[] = new int[21]; private int currentRoll = 0;

public void roll(int pins) { score += pins; rolls[currentRoll++] = pins; }

public int score() { return score; }}

- ugly comment in test.

Page 128: Scrum and Hyper-productivity Object Mentor, Inc. Copyright  1998-2007 by Object Mentor, Inc All Rights Reserved fitnesse.org

128

The Third test.import junit.framework.TestCase;

public class BowlingGameTest extends TestCase { private Game g;

protected void setUp() throws Exception { g = new Game(); }

private void rollMany(int n, int pins) { for (int i = 0; i < n; i++) g.roll(pins); }

public void testGutterGame() throws Exception { rollMany(20, 0); assertEquals(0, g.score()); }

public void testAllOnes() throws Exception { rollMany(20,1); assertEquals(20, g.score()); }

// public void testOneSpare() throws Exception {// g.roll(5);// g.roll(5); // spare// g.roll(3);// rollMany(17,0);// assertEquals(16,g.score());// }}

public class Game { private int score = 0; private int rolls[] = new int[21]; private int currentRoll = 0;

public void roll(int pins) { score += pins; rolls[currentRoll++] = pins; }

public int score() { int score = 0; for (int i = 0; i < rolls.length; i++) score += rolls[i]; return score; }}

- ugly comment in test.

Page 129: Scrum and Hyper-productivity Object Mentor, Inc. Copyright  1998-2007 by Object Mentor, Inc All Rights Reserved fitnesse.org

129

The Third test.import junit.framework.TestCase;

public class BowlingGameTest extends TestCase { private Game g;

protected void setUp() throws Exception { g = new Game(); }

private void rollMany(int n, int pins) { for (int i = 0; i < n; i++) g.roll(pins); }

public void testGutterGame() throws Exception { rollMany(20, 0); assertEquals(0, g.score()); }

public void testAllOnes() throws Exception { rollMany(20,1); assertEquals(20, g.score()); }

// public void testOneSpare() throws Exception {// g.roll(5);// g.roll(5); // spare// g.roll(3);// rollMany(17,0);// assertEquals(16,g.score());// }}

public class Game { private int rolls[] = new int[21]; private int currentRoll = 0;

public void roll(int pins) { rolls[currentRoll++] = pins; }

public int score() { int score = 0; for (int i = 0; i < rolls.length; i++) score += rolls[i]; return score; }}

- ugly comment in test.

Page 130: Scrum and Hyper-productivity Object Mentor, Inc. Copyright  1998-2007 by Object Mentor, Inc All Rights Reserved fitnesse.org

130

The Third test.import junit.framework.TestCase;

public class BowlingGameTest extends TestCase { private Game g;

protected void setUp() throws Exception { g = new Game(); }

private void rollMany(int n, int pins) { for (int i = 0; i < n; i++) g.roll(pins); }

public void testGutterGame() throws Exception { rollMany(20, 0); assertEquals(0, g.score()); }

public void testAllOnes() throws Exception { rollMany(20,1); assertEquals(20, g.score()); }

public void testOneSpare() throws Exception { g.roll(5); g.roll(5); // spare g.roll(3); rollMany(17,0); assertEquals(16,g.score()); }}

public class Game { private int rolls[] = new int[21]; private int currentRoll = 0;

public void roll(int pins) { rolls[currentRoll++] = pins; }

public int score() { int score = 0; for (int i = 0; i < rolls.length; i++) score += rolls[i]; return score; }}

expected:<16> but was:<13>

- ugly comment in test.

Page 131: Scrum and Hyper-productivity Object Mentor, Inc. Copyright  1998-2007 by Object Mentor, Inc All Rights Reserved fitnesse.org

131

The Third test.import junit.framework.TestCase;

public class BowlingGameTest extends TestCase { private Game g;

protected void setUp() throws Exception { g = new Game(); }

private void rollMany(int n, int pins) { for (int i = 0; i < n; i++) g.roll(pins); }

public void testGutterGame() throws Exception { rollMany(20, 0); assertEquals(0, g.score()); }

public void testAllOnes() throws Exception { rollMany(20,1); assertEquals(20, g.score()); }

public void testOneSpare() throws Exception { g.roll(5); g.roll(5); // spare g.roll(3); rollMany(17,0); assertEquals(16,g.score()); }}

public class Game { private int rolls[] = new int[21]; private int currentRoll = 0;

public void roll(int pins) { rolls[currentRoll++] = pins; }

public int score() { int score = 0; for (int i = 0; i < rolls.length; i++) { if (rolls[i] + rolls[i+1] == 10) // spare score += ... score += rolls[i]; } return score; }}

This isn’t going to work because i might not refer to the first ball of the frame.

Design is still wrong.

Need to walk through array two balls (one frame) at a time.

- ugly comment in test.

Page 132: Scrum and Hyper-productivity Object Mentor, Inc. Copyright  1998-2007 by Object Mentor, Inc All Rights Reserved fitnesse.org

132

The Third test.import junit.framework.TestCase;

public class BowlingGameTest extends TestCase { private Game g;

protected void setUp() throws Exception { g = new Game(); }

private void rollMany(int n, int pins) { for (int i = 0; i < n; i++) g.roll(pins); }

public void testGutterGame() throws Exception { rollMany(20, 0); assertEquals(0, g.score()); }

public void testAllOnes() throws Exception { rollMany(20,1); assertEquals(20, g.score()); }

// public void testOneSpare() throws Exception {// g.roll(5);// g.roll(5); // spare// g.roll(3);// rollMany(17,0);// assertEquals(16,g.score());// }}

public class Game { private int rolls[] = new int[21]; private int currentRoll = 0;

public void roll(int pins) { rolls[currentRoll++] = pins; }

public int score() { int score = 0; for (int i = 0; i < rolls.length; i++) score += rolls[i]; return score; }}

- ugly comment in test.

Page 133: Scrum and Hyper-productivity Object Mentor, Inc. Copyright  1998-2007 by Object Mentor, Inc All Rights Reserved fitnesse.org

133

The Third test.import junit.framework.TestCase;

public class BowlingGameTest extends TestCase { private Game g;

protected void setUp() throws Exception { g = new Game(); }

private void rollMany(int n, int pins) { for (int i = 0; i < n; i++) g.roll(pins); }

public void testGutterGame() throws Exception { rollMany(20, 0); assertEquals(0, g.score()); }

public void testAllOnes() throws Exception { rollMany(20,1); assertEquals(20, g.score()); }

// public void testOneSpare() throws Exception {// g.roll(5);// g.roll(5); // spare// g.roll(3);// rollMany(17,0);// assertEquals(16,g.score());// }}

public class Game { private int rolls[] = new int[21]; private int currentRoll = 0;

public void roll(int pins) { rolls[currentRoll++] = pins; }

public int score() { int score = 0; int i = 0; for (int frame = 0; frame < 10; frame++) { score += rolls[i] + rolls[i+1]; i += 2; } return score; }}

- ugly comment in test.

Page 134: Scrum and Hyper-productivity Object Mentor, Inc. Copyright  1998-2007 by Object Mentor, Inc All Rights Reserved fitnesse.org

134

The Third test.import junit.framework.TestCase;

public class BowlingGameTest extends TestCase { private Game g;

protected void setUp() throws Exception { g = new Game(); }

private void rollMany(int n, int pins) { for (int i = 0; i < n; i++) g.roll(pins); }

public void testGutterGame() throws Exception { rollMany(20, 0); assertEquals(0, g.score()); }

public void testAllOnes() throws Exception { rollMany(20,1); assertEquals(20, g.score()); }

public void testOneSpare() throws Exception { g.roll(5); g.roll(5); // spare g.roll(3); rollMany(17,0); assertEquals(16,g.score()); }}

public class Game { private int rolls[] = new int[21]; private int currentRoll = 0;

public void roll(int pins) { rolls[currentRoll++] = pins; }

public int score() { int score = 0; int i = 0; for (int frame = 0; frame < 10; frame++) { score += rolls[i] + rolls[i+1]; i += 2; } return score; }}

expected:<16> but was:<13>

- ugly comment in test.

Page 135: Scrum and Hyper-productivity Object Mentor, Inc. Copyright  1998-2007 by Object Mentor, Inc All Rights Reserved fitnesse.org

135

The Third test.import junit.framework.TestCase;

public class BowlingGameTest extends TestCase { private Game g;

protected void setUp() throws Exception { g = new Game(); }

private void rollMany(int n, int pins) { for (int i = 0; i < n; i++) g.roll(pins); }

public void testGutterGame() throws Exception { rollMany(20, 0); assertEquals(0, g.score()); }

public void testAllOnes() throws Exception { rollMany(20,1); assertEquals(20, g.score()); }

public void testOneSpare() throws Exception { g.roll(5); g.roll(5); // spare g.roll(3); rollMany(17,0); assertEquals(16,g.score()); }}

public class Game { private int rolls[] = new int[21]; private int currentRoll = 0;

public void roll(int pins) { rolls[currentRoll++] = pins; }

public int score() { int score = 0; int i = 0; for (int frame = 0; frame < 10; frame++) { if (rolls[i] + rolls[i + 1] == 10) // spare { score += 10 + rolls[i + 2]; i += 2; } else { score += rolls[i] + rolls[i + 1]; i += 2; } } return score; }}

- ugly comment in test.

Page 136: Scrum and Hyper-productivity Object Mentor, Inc. Copyright  1998-2007 by Object Mentor, Inc All Rights Reserved fitnesse.org

136

The Third test.import junit.framework.TestCase;

public class BowlingGameTest extends TestCase { private Game g;

protected void setUp() throws Exception { g = new Game(); }

private void rollMany(int n, int pins) { for (int i = 0; i < n; i++) g.roll(pins); }

public void testGutterGame() throws Exception { rollMany(20, 0); assertEquals(0, g.score()); }

public void testAllOnes() throws Exception { rollMany(20,1); assertEquals(20, g.score()); }

public void testOneSpare() throws Exception { g.roll(5); g.roll(5); // spare g.roll(3); rollMany(17,0); assertEquals(16,g.score()); }}

public class Game { private int rolls[] = new int[21]; private int currentRoll = 0;

public void roll(int pins) { rolls[currentRoll++] = pins; }

public int score() { int score = 0; int i = 0; for (int frame = 0; frame < 10; frame++) { if (rolls[i] + rolls[i + 1] == 10) // spare { score += 10 + rolls[i + 2]; i += 2; } else { score += rolls[i] + rolls[i + 1]; i += 2; } } return score; }}

-ugly comment in test.-ugly comment in conditional.-i is a bad name for this variable

Page 137: Scrum and Hyper-productivity Object Mentor, Inc. Copyright  1998-2007 by Object Mentor, Inc All Rights Reserved fitnesse.org

137

The Third test.import junit.framework.TestCase;

public class BowlingGameTest extends TestCase { private Game g;

protected void setUp() throws Exception { g = new Game(); }

private void rollMany(int n, int pins) { for (int i = 0; i < n; i++) g.roll(pins); }

public void testGutterGame() throws Exception { rollMany(20, 0); assertEquals(0, g.score()); }

public void testAllOnes() throws Exception { rollMany(20,1); assertEquals(20, g.score()); }

public void testOneSpare() throws Exception { g.roll(5); g.roll(5); // spare g.roll(3); rollMany(17,0); assertEquals(16,g.score()); }}

public class Game { private int rolls[] = new int[21]; private int currentRoll = 0;

public void roll(int pins) { rolls[currentRoll++] = pins; }

public int score() { int score = 0; int frameIndex = 0; for (int frame = 0; frame < 10; frame++) { if (rolls[frameIndex] + rolls[frameIndex + 1] == 10) // spare { score += 10 + rolls[frameIndex + 2]; frameIndex += 2; } else { score += rolls[frameIndex] + rolls[frameIndex + 1]; frameIndex += 2; } } return score; }}

-ugly comment in test.-ugly comment in conditional.

Page 138: Scrum and Hyper-productivity Object Mentor, Inc. Copyright  1998-2007 by Object Mentor, Inc All Rights Reserved fitnesse.org

138

The Third test.import junit.framework.TestCase;

public class BowlingGameTest extends TestCase { private Game g;

protected void setUp() throws Exception { g = new Game(); }

private void rollMany(int n, int pins) { for (int i = 0; i < n; i++) g.roll(pins); }

public void testGutterGame() throws Exception { rollMany(20, 0); assertEquals(0, g.score()); }

public void testAllOnes() throws Exception { rollMany(20,1); assertEquals(20, g.score()); }

public void testOneSpare() throws Exception { g.roll(5); g.roll(5); // spare g.roll(3); rollMany(17,0); assertEquals(16,g.score()); }}

public class Game { private int rolls[] = new int[21]; private int currentRoll = 0;

public void roll(int pins) { rolls[currentRoll++] = pins; }

public int score() { int score = 0; int frameIndex = 0; for (int frame = 0; frame < 10; frame++) { if (isSpare(frameIndex)) { score += 10 + rolls[frameIndex + 2]; frameIndex += 2; } else { score += rolls[frameIndex] + rolls[frameIndex + 1]; frameIndex += 2; } } return score; }

private boolean isSpare(int frameIndex) { return rolls[frameIndex] + rolls[frameIndex + 1] == 10; }}

-ugly comment in test.

Page 139: Scrum and Hyper-productivity Object Mentor, Inc. Copyright  1998-2007 by Object Mentor, Inc All Rights Reserved fitnesse.org

139

The Third test.import junit.framework.TestCase;

public class BowlingGameTest extends TestCase { private Game g;

protected void setUp() throws Exception { g = new Game(); }

private void rollMany(int n, int pins) { for (int i = 0; i < n; i++) g.roll(pins); }

public void testGutterGame() throws Exception { rollMany(20, 0); assertEquals(0, g.score()); }

public void testAllOnes() throws Exception { rollMany(20,1); assertEquals(20, g.score()); }

public void testOneSpare() throws Exception { rollSpare(); g.roll(3); rollMany(17,0); assertEquals(16,g.score()); }

private void rollSpare() { g.roll(5); g.roll(5); }}

public class Game { private int rolls[] = new int[21]; private int currentRoll = 0;

public void roll(int pins) { rolls[currentRoll++] = pins; }

public int score() { int score = 0; int frameIndex = 0; for (int frame = 0; frame < 10; frame++) { if (isSpare(frameIndex)) { score += 10 + rolls[frameIndex + 2]; frameIndex += 2; } else { score += rolls[frameIndex] + rolls[frameIndex + 1]; frameIndex += 2; } } return score; }

private boolean isSpare(int frameIndex) { return rolls[frameIndex] + rolls[frameIndex + 1] == 10; }}

-

Page 140: Scrum and Hyper-productivity Object Mentor, Inc. Copyright  1998-2007 by Object Mentor, Inc All Rights Reserved fitnesse.org

140

The Fourth test.import junit.framework.TestCase;

public class BowlingGameTest extends TestCase { ...

public void testGutterGame() throws Exception { rollMany(20, 0); assertEquals(0, g.score()); }

public void testAllOnes() throws Exception { rollMany(20,1); assertEquals(20, g.score()); }

public void testOneSpare() throws Exception { rollSpare(); g.roll(3); rollMany(17,0); assertEquals(16,g.score()); }

public void testOneStrike() throws Exception { g.roll(10); // strike g.roll(3); g.roll(4); rollMany(16, 0); assertEquals(24, g.score()); }

private void rollSpare() { g.roll(5); g.roll(5); }}

public class Game { private int rolls[] = new int[21]; private int currentRoll = 0;

public void roll(int pins) { rolls[currentRoll++] = pins; }

public int score() { int score = 0; int frameIndex = 0; for (int frame = 0; frame < 10; frame++) { if (isSpare(frameIndex)) { score += 10 + rolls[frameIndex + 2]; frameIndex += 2; } else { score += rolls[frameIndex] + rolls[frameIndex + 1]; frameIndex += 2; } } return score; }

private boolean isSpare(int frameIndex) { return rolls[frameIndex] + rolls[frameIndex + 1] == 10; }}

- ugly comment in testOneStrike.

expected:<24> but was:<17>

Page 141: Scrum and Hyper-productivity Object Mentor, Inc. Copyright  1998-2007 by Object Mentor, Inc All Rights Reserved fitnesse.org

141

The Fourth test.import junit.framework.TestCase;

public class BowlingGameTest extends TestCase { ...

public void testGutterGame() throws Exception { rollMany(20, 0); assertEquals(0, g.score()); }

public void testAllOnes() throws Exception { rollMany(20,1); assertEquals(20, g.score()); }

public void testOneSpare() throws Exception { rollSpare(); g.roll(3); rollMany(17,0); assertEquals(16,g.score()); }

public void testOneStrike() throws Exception { g.roll(10); // strike g.roll(3); g.roll(4); rollMany(16, 0); assertEquals(24, g.score()); }

private void rollSpare() { g.roll(5); g.roll(5); }}

public class Game { private int rolls[] = new int[21]; private int currentRoll = 0;

public void roll(int pins) { rolls[currentRoll++] = pins; }

public int score() { int score = 0; int frameIndex = 0; for (int frame = 0; frame < 10; frame++) { if (rolls[frameIndex] == 10) // strike { score += 10 + rolls[frameIndex+1] + rolls[frameIndex+2]; frameIndex++; } else if (isSpare(frameIndex)) { score += 10 + rolls[frameIndex + 2]; frameIndex += 2; } else { score += rolls[frameIndex] + rolls[frameIndex + 1]; frameIndex += 2; } } return score; }

private boolean isSpare(int frameIndex) { return rolls[frameIndex] + rolls[frameIndex + 1] == 10; }}

-ugly comment in testOneStrike.-ugly comment in conditional.-ugly expressions.

Page 142: Scrum and Hyper-productivity Object Mentor, Inc. Copyright  1998-2007 by Object Mentor, Inc All Rights Reserved fitnesse.org

142

The Fourth test.import junit.framework.TestCase;

public class BowlingGameTest extends TestCase { ...

public void testGutterGame() throws Exception { rollMany(20, 0); assertEquals(0, g.score()); }

public void testAllOnes() throws Exception { rollMany(20,1); assertEquals(20, g.score()); }

public void testOneSpare() throws Exception { rollSpare(); g.roll(3); rollMany(17,0); assertEquals(16,g.score()); }

public void testOneStrike() throws Exception { g.roll(10); // strike g.roll(3); g.roll(4); rollMany(16, 0); assertEquals(24, g.score()); }

private void rollSpare() { g.roll(5); g.roll(5); }}

public class Game { private int rolls[] = new int[21]; private int currentRoll = 0;

public void roll(int pins) { rolls[currentRoll++] = pins; }

public int score() { int score = 0; int frameIndex = 0; for (int frame = 0; frame < 10; frame++) { if (rolls[frameIndex] == 10) // strike { score += 10 + strikeBonus(frameIndex); frameIndex++; } else if (isSpare(frameIndex)) { score += 10 + spareBonus(frameIndex); frameIndex += 2; } else { score += sumOfBallsInFrame(frameIndex); frameIndex += 2; } } return score; }

private int sumOfBallsInFrame(int frameIndex) { return rolls[frameIndex]+rolls[frameIndex+1]; }

private int spareBonus(int frameIndex) { return rolls[frameIndex + 2]; }

private int strikeBonus(int frameIndex) { return rolls[frameIndex+1]+rolls[frameIndex+2]; }

private boolean isSpare(int frameIndex) { return rolls[frameIndex]+rolls[frameIndex+1] == 10; }}

-ugly comment in testOneStrike.-ugly comment in conditional.

Page 143: Scrum and Hyper-productivity Object Mentor, Inc. Copyright  1998-2007 by Object Mentor, Inc All Rights Reserved fitnesse.org

143

The Fourth test.import junit.framework.TestCase;

public class BowlingGameTest extends TestCase { ...

public void testGutterGame() throws Exception { rollMany(20, 0); assertEquals(0, g.score()); }

public void testAllOnes() throws Exception { rollMany(20,1); assertEquals(20, g.score()); }

public void testOneSpare() throws Exception { rollSpare(); g.roll(3); rollMany(17,0); assertEquals(16,g.score()); }

public void testOneStrike() throws Exception { g.roll(10); // strike g.roll(3); g.roll(4); rollMany(16, 0); assertEquals(24, g.score()); }

private void rollSpare() { g.roll(5); g.roll(5); }}

public class Game { private int rolls[] = new int[21]; private int currentRoll = 0;

public void roll(int pins) { rolls[currentRoll++] = pins; }

public int score() { int score = 0; int frameIndex = 0; for (int frame = 0; frame < 10; frame++) { if (isStrike(frameIndex)) { score += 10 + strikeBonus(frameIndex); frameIndex++; } else if (isSpare(frameIndex)) { score += 10 + spareBonus(frameIndex); frameIndex += 2; } else { score += sumOfBallsInFrame(frameIndex); frameIndex += 2; } } return score; }

private boolean isStrike(int frameIndex) { return rolls[frameIndex] == 10; }

private int sumOfBallsInFrame(int frameIndex) { return rolls[frameIndex] + rolls[frameIndex+1]; }

private int spareBonus(int frameIndex) { return rolls[frameIndex+2]; }

private int strikeBonus(int frameIndex) { return rolls[frameIndex+1] + rolls[frameIndex+2]; }

private boolean isSpare(int frameIndex) { return rolls[frameIndex]+rolls[frameIndex+1] == 10; }}

-ugly comment in testOneStrike.

Page 144: Scrum and Hyper-productivity Object Mentor, Inc. Copyright  1998-2007 by Object Mentor, Inc All Rights Reserved fitnesse.org

144

The Fourth test. ... public void testGutterGame() throws Exception { rollMany(20, 0); assertEquals(0, g.score()); }

public void testAllOnes() throws Exception { rollMany(20,1); assertEquals(20, g.score()); }

public void testOneSpare() throws Exception { rollSpare(); g.roll(3); rollMany(17,0); assertEquals(16,g.score()); }

public void testOneStrike() throws Exception { rollStrike(); g.roll(3); g.roll(4); rollMany(16, 0); assertEquals(24, g.score()); }

private void rollStrike() { g.roll(10); }

private void rollSpare() { g.roll(5); g.roll(5); }}

public class Game { private int rolls[] = new int[21]; private int currentRoll = 0;

public void roll(int pins) { rolls[currentRoll++] = pins; }

public int score() { int score = 0; int frameIndex = 0; for (int frame = 0; frame < 10; frame++) { if (isStrike(frameIndex)) { score += 10 + strikeBonus(frameIndex); frameIndex++; } else if (isSpare(frameIndex)) { score += 10 + spareBonus(frameIndex); frameIndex += 2; } else { score += sumOfBallsInFrame(frameIndex); frameIndex += 2; } } return score; }

private boolean isStrike(int frameIndex) { return rolls[frameIndex] == 10; }

private int sumOfBallsInFrame(int frameIndex) { return rolls[frameIndex] + rolls[frameIndex+1]; }

private int spareBonus(int frameIndex) { return rolls[frameIndex+2]; }

private int strikeBonus(int frameIndex) { return rolls[frameIndex+1] + rolls[frameIndex+2]; }

private boolean isSpare(int frameIndex) { return rolls[frameIndex]+rolls[frameIndex+1] == 10; }}

Page 145: Scrum and Hyper-productivity Object Mentor, Inc. Copyright  1998-2007 by Object Mentor, Inc All Rights Reserved fitnesse.org

145

The Fifth test. ... public void testGutterGame() throws Exception { rollMany(20, 0); assertEquals(0, g.score()); }

public void testAllOnes() throws Exception { rollMany(20,1); assertEquals(20, g.score()); }

public void testOneSpare() throws Exception { rollSpare(); g.roll(3); rollMany(17,0); assertEquals(16,g.score()); }

public void testOneStrike() throws Exception { rollStrike(); g.roll(3); g.roll(4); rollMany(16, 0); assertEquals(24, g.score()); }

public void testPerfectGame() throws Exception { rollMany(12,10); assertEquals(300, g.score()); }

private void rollStrike() { g.roll(10); }

private void rollSpare() { g.roll(5); g.roll(5); }}

public class Game { private int rolls[] = new int[21]; private int currentRoll = 0;

public void roll(int pins) { rolls[currentRoll++] = pins; }

public int score() { int score = 0; int frameIndex = 0; for (int frame = 0; frame < 10; frame++) { if (isStrike(frameIndex)) { score += 10 + strikeBonus(frameIndex); frameIndex++; } else if (isSpare(frameIndex)) { score += 10 + spareBonus(frameIndex); frameIndex += 2; } else { score += sumOfBallsInFrame(frameIndex); frameIndex += 2; } } return score; }

private boolean isStrike(int frameIndex) { return rolls[frameIndex] == 10; }

private int sumOfBallsInFrame(int frameIndex) { return rolls[frameIndex] + rolls[frameIndex+1]; }

private int spareBonus(int frameIndex) { return rolls[frameIndex+2]; }

private int strikeBonus(int frameIndex) { return rolls[frameIndex+1] + rolls[frameIndex+2]; }

private boolean isSpare(int frameIndex) { return rolls[frameIndex]+rolls[frameIndex+1] == 10; }}

Page 146: Scrum and Hyper-productivity Object Mentor, Inc. Copyright  1998-2007 by Object Mentor, Inc All Rights Reserved fitnesse.org

End

Page 147: Scrum and Hyper-productivity Object Mentor, Inc. Copyright  1998-2007 by Object Mentor, Inc All Rights Reserved fitnesse.org

147

Contact Information

Robert C. [email protected]

Website:www.objectmentor.com

FitNesse:www.fitnesse.org