+ All Categories
Home > Documents > Scrum and Hyper-productivity Object Mentor, Inc. Copyright 1998-2007 by Object Mentor, Inc All...

Scrum and Hyper-productivity Object Mentor, Inc. Copyright 1998-2007 by Object Mentor, Inc All...

Date post: 11-Jan-2016
Category:
Upload: millicent-newton
View: 215 times
Download: 2 times
Share this document with a friend
Popular Tags:
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
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


Recommended