[G_PRO] Basis Programmeren en OO Programmeren
DigitAP
  • Welkom
  • Inleiding
    • Benodigdheden
    • Afspraken code
    • Afspraken oefeningen
    • Nuttige extras
    • Dankwoord
    • Mee helpen?
  • Semester 1: Programming Principles
    • H1: Werken met Visual Studio
      • Introductie tot C#
      • Visual Studio en .NET Core installeren
      • Een C# project maken in Visual Studio
      • Fouten in je code
      • Je eerste stappen in C#
      • Input/Output: ReadLine/WriteLine
      • Kleuren in Console
      • Oefeningen
    • H2: Variabelen en datatypes
      • De syntaxis van C#
      • Datatypes
      • Variabelen
      • Expressies en operators
      • Oefeningen
    • H3: Strings en hun methoden
      • Strings
      • Strings samenvoegen
      • Omzetten van en naar strings
      • Functionaliteit van strings
      • Oefeningen
    • H4: Beslissingen
      • Beslissingen intro
      • Enkelvoudige booleaanse expressies
      • If, else, else if
      • Samengestelde booleaanse expressies
      • Scope van variabelen
      • Switch
      • Oefeningen
    • H5: Loops
      • Loops intro
      • While en Do While
      • For
      • Debuggen
      • Oefeningen
    • H6: Arrays
      • Array principes
      • Alternatieve syntax
      • Werken met arrays
      • Defaultwaarden
      • List<T>
      • Oefeningen
    • H7: Methoden
      • Methoden intro
      • Parameters
      • Return waarden
      • Geavanceerde methoden
      • Oefeningen
    • Intermezzo: TextCell
    • H8: Numerieke data
      • De Math klasse
      • Random
      • Casting en conversie
      • Oefeningen
    • H9: Meerdimensionaal werken
      • N-dimensionale arrays
      • Geneste iteratie
      • Oefeningen
    • H10: Gevorderde tekstverwerking
      • Voorstelling van tekst
      • Interpolatie met formattering
      • Werken met arrays van strings
      • Input en output van tekstbestanden
      • Oefeningen
    • Afsluiter: TextCell2D
  • Semester 2 : OOP
    • H10: Klassen en objecten
      • OOP Intro
      • Klassen en objecten aanmaken
      • DateTime: leren werken met objecten
      • Enumeraties: nog een eigen datatype
      • Klassen en objecten weergeven deel 1
      • Attributen
      • Methoden
      • Access modifiers
      • Properties
      • Oefeningen
    • H11: Objecten (al dan niet) aanmaken
      • Constructors
      • Spelen met strings
      • Oefeningen
    • H12: Geheugenmanagement bij klassen
      • value en reference met eigen objecten
      • nullable value types
      • NullReference exception
      • Oefeningen
    • H13: Datastructuren
      • Foreach en var
      • List
      • Dictionary
      • Immutable datastructuren
      • Verdere datastructuren
      • Oefeningen
    • H14: Overerving
      • Overerving intro
      • Virtual en override
      • Abstract
      • Constructors bij overerving
      • Oefeningen
    • H15: Geavanceerde overerving
      • protected access modifier
      • Base keyword
      • System.Object
      • Oefeningen
    • H16: Exception handling
      • Werken met exceptions
      • Zelf uitzonderingen maken
      • Wanneer exceptions en handling gebruiken
      • Oefeningen
    • H17: Polymorfisme en interfaces
      • Polymorfisme
      • Polymorfisme in de praktijk
      • Interfaces
      • Losse koppeling
      • Oefeningen
    • H18: Testing
      • Intro Testing
      • Wat is Unit Testing
      • Waarom Unit Testing?
      • Wanneer Unit Testing?
      • Schrijven van een unit test: AAA methode
      • Eerste voorbeeld: Sum
      • Assert
      • Oefening even of oneven getal
      • TestInitialize en DataRows
      • Oefening BMI
      • Exception testing
      • Oefening BMI exception
      • Oefening SchoolAdmin test null-waarden en TestCleanup
      • Oefening SchoolAdmin test equals
      • Oefening SchoolAdmin test cursus zoeken met id
      • Dependencies bij Unit Testing
      • Mocking
      • Oefeningen Mocking
      • Test Driven Development
      • Class Library
      • Oefeningen TDD
    • H19: SOLID
      • Single Responsibility Principle (SRP)
      • Open/Closed Principle (OCP)
      • Liskov Substitution Principle (LSP)
      • Interface Segregation Principle (ISP)
      • Dependency Inversion Principle (DIP)
  • Appendix
    • Visual Studio Tips & Tricks
    • Ea-ict coding guidelines
    • Oefeningen kerkhof
  • Semester 1 appendix
    • Nice to know stuff
      • Out en Ref parameters
      • Jagged arrays
    • All-In-Projecten
      • Overzicht
      • Console Matrix
      • Ascii filmpjes maken met loops
      • Ascii filmpjes maken met methoden
      • Fun with methods: een verhaalgenerator
      • Tekst-gebaseerd Maze game
      • Conway game of life
  • Semester 2 appendix
    • Operator overloading
    • Object Initializer Syntax
    • Compositie en aggregatie
    • Nice to know stuff
      • Klassen herbruiken
      • Expression bodied members
    • All-In-Projecten
      • Overzicht
      • OO Textbased Game
      • War Simulator
      • Map Maker
      • Magic The Gathering API
      • SchoolAdmin
  • Pro (geen leerstof en/of in opbouw)
    • Bitwise operators
    • Generics en collections
      • Generics methoden en types
      • Generic classes en constraints
      • Collections
      • Labo-oefeningen
    • Events
      • Events
      • Chat server
    • Software engineering
      • SOLID
Powered by GitBook
On this page
  • Stap 0: Inleiding
  • Stap 1: De eerste test
  • Stap 1.1:
  • Stap 2: De tweede test
  • Stap 2.1:
  • Stap 2.2:
  • Stap 2.3:
  • Stap 3: De derde test
  • Stap 3.1:
  • Stap 3.2:
  • Stap 3.3:
  • Stap 4: De vierde test
  • Stap 4.0:
  • Stap 4.1:
  • Stap 4.2:
  • Stap 4.3:
  • Stap 5: De vijfde test
  • Stap 6: De zesde test
Export as PDF
  1. Semester 2 : OOP
  2. H18: Testing

Oefeningen TDD

PreviousClass LibraryNextH19: SOLID

Last updated 1 year ago

Stap 0: Inleiding

In deze oefening gaan we met behulp van TDD een programma schrijven die de score gaat berekenen van een volledig spelletje bowling. Voor diegenen die nog nooit gebowld hebben of niet juist weten hoe de puntentelling is opgebouwd; hieronder vind je enkele links naar info:

Je moet dus de totale score van een spelletje berekenen, niet de lopende score weergeven (niet zoals de calculator dus).

De oefening wordt begeleid in stappen, het is de bedoeling dat je deze stappen volgt.

We gebruiken TDD als methode. Dat houdt dus in dat we de Red, Green, Refactor cyclus gaan volgen.

Stap 1: De eerste test

Zet alles klaar voor de eerste test: Maak een nieuw project BowlingGameScore en voeg een NUnit Test Project BowlingGameTests toe. Vergeet de 'Project Reference' en de using niet. Probeer in methode Test1 een instantie te maken van een klasse BowlingGame.

Stap 1.1:

Zorg ervoor dat deze test slaagt. Let op: vermijd het schrijven van extra code. Creëer een nieuwe klasse BowlingGame.

Stap 2: De tweede test

Een volgende stap is dat we de score van een complete off-day game testen. De in bowlingmiddens bekende GlutterGame, Je gooit je bowlingbal steeds in de goot.

Stap 2.1:

Schrijf de test When_Roll_GlutterGame_Returns_0(). Je creëert eerst een BowlingGame object. Roep 20 keer de (nog onbestaande) methode Roll aan met argument 0 (aantal kegels omvergeworpen) en vergelijk de score (property Score van class BowlingGame) met het verwachte resultaat. Deze test faalt (implementatie is nog niet verwezenlijkt).

Stap 2.2:

Zorg dat de tweede test slaagt. Creëer een methode Roll die een integer argument heeft (het aantal omgeworpen kegels) en creëer een property die de score bijhoudt. Je hoeft er enkel voor te zorgen dat deze test slaagt.

Stap 2.3:

Refactor je testen. De eerste test zit volledig in de tweede test, nl het instantiëren van het BowlingGame object. Je kan de eerste test dus schrappen. Doe dat. Laat de test(en) lopen en verifieer dat ze slaagt.

Stap 3: De derde test

Een mogelijke volgende stap is een game waarin je bij elke worp een 1 gooit.

Stap 3.1:

Schrijf de test When_Roll_AllOnes_Returns_20(). Je creëert eerst een BowlingGame object. Roep 20 keer de methode Roll aan met argument 1 (aantal kegels omvergeworpen) en vergelijk de score (property Score van class BowlingGame) met het verwachte resultaat. Deze test faalt (implementatie van Roll is nog niet juist).

Stap 3.2:

Zorg dat de derde test slaagt. Verbeter de methode Roll zodat bij elke nieuwe worp de punten van de omgevallen kegels bij de score worden geteld.

Stap 3.3:

Refactor je testen en de code. Allereerst maak je de setter van de property Score private. Test na je aanpassing opnieuw. Vervolgens kan je herhaalde code voor de instantiatie van het BowlingGame object verbeteren. Dat hebben we nog niet gezien in de cursus, dus dat krijg je cadeau:

public class BowlingGameScoreTests
{
    private BowlingGame game;

    [SetUp]
    public void Setup()
    {
        game = new BowlingGame();
    }

    [Test]
    public void When_Roll_GutterGame_Returns_0()

Verwijder de instantiatie van het BowlingGame object uit je testen. Test opnieuw. Het testen is belangrijk om te voorkomen dat je nieuwe problemen introduceert tijdens de refactoring. Je hebt waarschijnlijk twee identieke loops in je testen staan om 20 keer een 0 of een 1 te gooien. Vervang deze loops door een (private) method RollMany met twee integer parameters rolls (aantal keren) en pins (aantal omvergeworpen kegels). Test nadien opnieuw om te verifiëren dat alles nog correct werkt.

Stap 4: De vierde test

Tijd om een Spare te testen. Een Spare is in één frame 10 kegels omgooien. Opgelet, een frame kan bestaan uit 1 of 2 worpen. Als je bij de eerste worp 10 kegels omgooit heb je een strike. Daarover meer later. De score is dan de 10 van de frame + het aantal omgevallen kegels bij je volgende worp. Het voorbeeld dat je in je test kan gebruiken is worp 1 - 5 kegels, worp 2 - 5 kegels en worp 3 - 3 kegels gevolgd door allemaal gootjes. De uiteindelijke score is dan voor frame 1 - 13 + frame 2 - 3 = 16.

Stap 4.0:

Er is eerst wat refactoring nodig. Je hebt ten eerste het concept van frame dat we nog niet hebben meegenomen in de code. Verder heb je eigenlijk een historiek nodig van worpen om de score te kunnen bepalen. Je moet namelijk kunnen terugkijken naar een sequentie van worpen. Ook deze nieuwe code krijg je cadeau, maar je mag ook zelf eerst proberen of je er in lukt om de test hieronder te doen slagen. Doe in elk geval eerst de refactoring en blijf testen (zonder nieuwe test) alvorens je de nieuwe test schrijft.

Voor diegenen die er niet in slagen om de code te schrijven, of die de vraagstelling niet helemaal begrepen hebben volgt nu de nieuwe code. De nieuwe code doorloopt de tot nu toe gedefinieerde testen glansrijk:

using System;
using System.Collections.Generic;
using System.Text;

namespace BowlingGameScore
{
    public class BowlingGame
    {
        private int[] pins = new int[21];  // het aantal omgeworpen kegels per worp (maximaal 21 worpen laatste frame een spare + 1 of strike + 2;
        private int currentRoll = 0;       // teller van het aantal worpen die de gebruiker heeft gedaan
        
        public int Score
        {
            get 
            {
                int score = 0;
                int rollIndex = 0;
                for (int frame = 0; frame < 10; frame++) // loop over het aantal worpen
                {
                    score += pins[rollIndex] + pins[rollIndex + 1];
                    rollIndex += 2;
                }

                return score;
            }
        }
        public void Roll (int pinsThisRoll)
        {
            pins[currentRoll++] = pinsThisRoll;
        }
    }
}

Stap 4.1:

Schrijf de test When_Roll_SpareAndThree_Returns_16(). Je roept de juiste methodes aan om de worpen aan de scorecalculator aan te bieden en vergelijkt de score met het verwachte resultaat. Deze test faalt.

Stap 4.2:

Pas de code aan zodat de test slaagt.

Stap 4.3:

Je kan de test of je een Spare hebt vervangen dooe een methode IsSpare met parameter rollIndex. Vervang ook

score += pins[rollIndex] + pins[rollIndex + 1]

Door

 score += GetStandardScore(rollIndex);

En doe hetzelfde met je code voor de Spare score. Vergeet niet telkens te testen.

Stap 5: De vijfde test

De strike. Je eerste worp van een frame kegelt alle kegels om. De score is dan de 10 van de frame + het aantal omgevallen kegels bij je volgende twee worpen. Het voorbeeld dat je in je test kan gebruiken is worp 1 - 10 kegels, worp 2 - 3 kegels en worp 3 - 4 kegels gevolgd door allemaal gootjes. De uiteindelijke score is dan voor frame 1 - 17 + frame 2 (twee worpen) - 7 = 24.

Dit is identiek aan test 4.

Stap 6: De zesde test

Het perfecte spel, dus niets dan strikes: 10 frames met telkens 1 worp en vervolgens nog eens 2 strikes.

Doe wat moet gedaan worden. Noem je test When_Roll_PerfectGame_Returns_300. De score voor een perfecte game is 300. Hoeveel worpen heb je? Moet je je code nog aanpassen?

Puntentelling Bowling
Scorecalculator Bowling
Leren bowlen
42KB
BowlingGameScoreOplossing.zip
archive