230 likes | 373 Views
Testing. Test-first design GUIs and testing. Test-first design. More of a design technique than a testing technique End up with a lot of automated tests Almost, but not quite, unit tests. Example: Yahtzee. Five dice Various ways to make a score Reroll dice you don’t want two times
E N D
Testing Test-first design GUIs and testing
Test-first design • More of a design technique than a testing technique • End up with a lot of automated tests • Almost, but not quite, unit tests 428-11
Example: Yahtzee • Five dice • Various ways to make a score • Reroll dice you don’t want two times • Choose a scoring rule, then 428-11
Scoring rules • 1s – total value of 1s • 6s – total value of 6s • Three of a kind, four of a kind, chance – total • Full house – 25 • Low straight – 30 • High straight – 40 • Yahtzee - 50 428-11
Interface to Yahtzee object • valueOfFullHouse() • chooseFullHouse() • fullHouseIsChosen() • Before a rule is chosen, its value returns the value according to the current dice. Choosing a rule freezes its value. 428-11
Simpler interface to Yahtzee object • roll(sequence of numbers) sets the dice to the sequence of numbers • valueOfFullHouse() returns the value of the dice according to the Full House rule. 428-11
Typical test yahtzee.roll(2,3,4,5,6); assert(yahtzee.fullhouse()=0); assert(yahtzee.ones()=0); assert(yahtzee.sixes()=6); assert(yahtzee.highStraight()=40); assert(yahtzee.lowStraight()=30); assert(yahtzee.chance()=20); 428-11
Another test yahtzee.roll(6,6,6,6,6); assert(yahtzee.fullhouse()=25); assert(yahtzee.ones()=0); assert(yahtzee.sixes()=30); assert(yahtzee.highStraight()=0); assert(yahtzee.lowStraight()=0); assert(yahtzee.chance()=36); 428-11
chooseFullHouse() • Once a rule is chosen, its value does not change even when the dice are rerolled. • fullHouseIsChosen() 428-11
yahtzee.roll(2,3,4,5,6); assert(yahtzee.fullHouse()=0); assert(!yahtzee.fullHouseIsChosen()); yahtzee.chooseFullHouse(); yahtzee.roll(6,6,6,6,6); assert(yahtzee.fullhouse()=0); assert(yahtzee.fullHouseIsChosen()); 428-11
Choosing rules • Add a boolean variable fullHouseIsChosen • Add an integer variable fullHouseValue • chooseFullHouse() will save the current value and mark this rule as chosen • Change fullHouse() to first check whether the rule was chosen. If so, return the saved value. 428-11
Choosing rules • Exactly one rule is chosen each round. • Can role three times in each round. Once you choose a rule, the next role starts another round. • Can “freeze” dice, only roll unfrozen ones. 428-11
yahtzee.roll(2,3,4,6,6); • assert(yahtzee.sixes()=12); • assert(yahtzee.yahtzee()=0); • yahtzee.chooseFullHouse(); • yahtzee.freezeDice(false,false,false,true,true); • yahtzee.roll(6,6,6,1,1); • assert(yahtzee.fullhouse()=0); • assert(yahtzee.sixes()=30); • assert(yahtzee.yahtzee()=50);
Freezing dice • dieIsFrozen is an array of booleans • roll() only changes dice that are not frozen • Other variables of Yahtzee • rollNumber • ruleWasChosen • roll() increments rollNumber • If ruleWasChosen then roll() will reset rollNumber and ruleWasChosen. 428-11
yahtzee.roll(2,3,4,6,6); yahtzee.freezeDice(false,false,false,true,true); yahtzee.roll(5,6,6,1,1); yahtzee.freezeDice(false,true,true,true,true); yahtzee.roll(6,2,2,1,1); assert(yahtzee.sixes()=30); assert(yahtzee.yahtzee()=50); yahtzee.roll(3,2,2,1,1); assert(yahtzee.sixes()=30); yahtzee.chooseYahtzee(); yahtzee.roll(3,2,2,1,1); assert(yahtzee.sixes()=0);
Where did the tests come from? • What could go wrong? • Think of common errors • http://www.testing.com/writings/short-catalog.pdf (one page) and • http://www.testing.com/writings/catalog.pdf (23 pages) 428-11
A UI for Yahtzee • In VisualWorks • Create YahtzeeInterface, a subclass of ApplicationModel • Draw the GUI with the GUI Painter • Define an “aspect” for each field • Make a “roll” button that sends roll message 428-11
“roll” does the work roll | freezeDice | freezeDice := OrderedCollection new. freezeDice add: (f1 value); add: (f2 value); add: (f3 value); add: (f4 value); add: (f5 value). game freezeDice: freezeDice. game roll. die1 value: (game dice at: 1). die2 value: (game dice at: 2). die3 value: (game dice at: 3). die4 value: (game dice at: 4). die5 value: (game dice at: 5). 428-11
Secret of GUI • Do as little as possible in the GUI • Write tests for non-GUI • Build the non-GUI first • GUI is a thin layer, generated by a tool, and easy to debug 428-11
Summary • Writing tests first is a way to design the interface of your modules • Once the interface is designed, write more tests to improve the quality of the tests • Keep GUI as small as possible, then don’t worry about writing automated tests for it 428-11
Next time • FIT – see http://fit.c2.com/wiki.cgi?WelcomeVisitors • In particular, look at documents in “What’s What”, such as the Cook’s Tour. 428-11