[ PHPUnit ] ボーリングから考えるテスト駆動開発 7テスト目

これからはじめるTDD テスト駆動開発入門 ThinkIT Books より

# ボーリングの点数計算プログラムを作る

## ストライクとスペアの複合テストケース①

BowlingGameTestに以下の機能を実装。


### テストを書く

```php
    /**
     * ストライクとスペアが複合した場合のケース
     *
     * 1投目: ストライク
     * 2投目: 5
     * 3投目: 5 (スペア)
     * 4投目: 3
     *
     * 残りガター
     *
     */
    public function testStrikeAndSpare()
    {
        $this->BowlingGame->recordShot(10); //10+(5+5)
        $this->BowlingGame->recordShot(5); //5
        $this->BowlingGame->recordShot(5); //5+(3)
        $this->BowlingGame->recordShot(3); //3

        $this->loopRecordShot(15, 0);

        $this->assertEquals(36, $this->BowlingGame->calculateScore());
    }
```

### 実行して怒られる

```bash
FAILURES!
Tests: 8, Assertions: 8, Failures: 1.
```

### テストが通るように処理を書く(__最小の構成で__)

① 原因: スペアの判定がおかしい

- 現状2投目しかスペアの判定をしていない


② ストライク時に何投目かどうか判定している変数をリセット
次の投球が1投目として判定されるようにする

```php
    /**
     * ストライク時にボーナス管理の変数をセット
     * @param  int     $pin [description]
     * @return void      [description]
     */
    private function isStrike(int $pin)
    {
        if ($pin === 10) {

            $this->shotNo = 0;

            if ($this->strikeBonusCount !== 0) {
                $this->doubleBonusCount = 2;
            }

            if ($this->strikeBonusCount === 0) {
                $this->strikeBonusCount = 2;
            }
        }
    }
```

③ テスト

```bash
OK (8 tests, 8 assertions)
```

## ダブルストライクとスペアの複合テストケース②

### テストを書く

```php
    /**
     * ストライクとスペアが複合した場合のケース
     *
     * 1投目: ストライク
     * 2投目: 5
     * 3投目: 5 (スペア)
     * 4投目: 3
     *
     * 残りガター
     *
     */
    public function testStrikeAndSpare()
    {
        $this->BowlingGame->recordShot(10); //10+(5+5)
        $this->BowlingGame->recordShot(5); //5
        $this->BowlingGame->recordShot(5); //5+(3)
        $this->BowlingGame->recordShot(3); //3

        $this->loopRecordShot(15, 0);

        $this->assertEquals(36, $this->BowlingGame->calculateScore());
    }
```

### 実行
```bash
OK (9 tests, 9 assertions)
```

## リファクタリング

```php
　　/**
     * ボーリングの1投球の計算を実行させる
     *
     * @param int    $pin [description]
     * @return void
     */
    public function recordShot(int $pin)
    {
        ・・・

        $this->calculateSpare($pin);

        $this->calculateStrike($pin);

        ・・・
    }

    /**
     * ストライク時の得点計算
     * @param  int    $pin [description]
     * @return void      [description]
     */
    private function calculateStrike(int $pin)
    {
        if ($this->doubleBonusCount > 0) {
            $this->score += $pin;
            --$this->doubleBonusCount;
        }

        if ($this->strikeBonusCount > 0) {
            $this->score += $pin;
            --$this->strikeBonusCount;
        }
    }
```

### ストライクのボーナス計算を分解する

```php
    /**
     * ボーリングの1投球の計算を実行させる
     *
     * @param int    $pin [description]
     * @return void
     */
    public function recordShot(int $pin)
    {
        ・・・

        $this->calculateSpare($pin);

        $this->calculateStrikeBonus($pin);

        $this->calculateDoubleBonus($pin);

        ・・・
    }

    /**
     * ストライク時の得点計算
     * @param  int    $pin [description]
     * @return void      [description]
     */
    private function calculateStrikeBonus(int $pin)
    {
        if ($this->strikeBonusCount > 0) {
            $this->score += $pin;
            --$this->strikeBonusCount;
        }
    }

    /**
     * ダブル時の得点計算
     * @param  int    $pin [description]
     * @return void      [description]
     */
    private function calculateDoubleBonus(int $pin)
    {
        if ($this->doubleBonusCount > 0) {
            $this->score += $pin;
            --$this->doubleBonusCount;
        }
    }

```

### テスト

```bash
OK (9 tests, 9 assertions)
```

次回はフレームごとのスコアを計算する機能を実装。。。