LoginSignup
0
0

More than 5 years have passed since last update.

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

Posted at

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

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

フレーム単位でのスコアを取得する

ダブルストライクとターキーの処理を移していく

テスト

BowlingGameTest.php
    /**
     * 2球連続ストライクのケース
     *
     * 1投目: ストライク
     * 2投目: ストライク
     * 3投目: 3
     * 4投目: 1
     *
     * 残りガター
     *
     */
    public function testDoubleStrikeAtFirstFlame()
    {
        $this->BowlingGame->recordShot(10); //10+(10+3)
        $this->BowlingGame->recordShot(10); //10+(3+1)
        $this->BowlingGame->recordShot(3); //3
        $this->BowlingGame->recordShot(1); //1           [計41]

        $this->loopRecordShot(14, 0);

        $this->assertEquals(41, $this->BowlingGame->calculateScore());

        //ストライク時に1フレーム目と2フレーム目の点数がただし以下
        $this->assertEquals(23, $this->BowlingGame->flameScore(0));
        $this->assertEquals(14, $this->BowlingGame->flameScore(1));
    }

テスト実行

1) BowlingGameTest::testDoubleStrikeAtFirstFlame
Failed asserting that 20 matches expected 23.

/var/www/html/test/testDrivenBowling/tests/BowlingGameTest.php:142

FAILURES!
Tests: 18, Assertions: 32, Failures: 1.

ロジック修正

BowlingGame.php
    /** @var  int ダブルストライクのフレームを記録 */
    private $strikeDoubleFlameNo;

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

            //ダブルの一投目は二つ前のフレームに送る
            if ($this->doubleBonusCount === 2) {
                $this->Flames[$this->strikeDoubleFlameNo-1]->addBonus($pin);
            } else {
                $this->Flames[$this->strikeDoubleFlameNo]->addBonus($pin);
            }

            $this->score += $pin;
            --$this->doubleBonusCount;

        }
    }

/**
     * ストライク時にボーナス管理の変数をセット
     * @return void      [description]
     */
    private function isStrike()
    {
        if ($this->Flames[count($this->Flames)-1]->isStrike()) {

            $this->strikeFlameNo = count($this->Flames)-1;

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

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

テスト実行

OK (18 tests, 33 assertions)

オープンフレームの概念を取り込んでおく

  • ボーナス計算が発生しないフレームのこと

FlameにneedBonus()を実装し、スペアとストライク以外では
falseを返すようにする

一気にやることにします。
もうそろそろめんどくさくなってきたw

テスト

    /**
     * @test
     */
    public function _オープンフレームにボーナスは不要()
    {
        $this->Flame->recordShot(3);
        $this->Flame->recordShot(3);
        $this->assertFalse($this->Flame->needBonus());
    }

    /**
     * @test
     */
    public function _スペアのボーナスは1投分で完了()
    {
        $this->Flame->recordShot(5);
        $this->Flame->recordShot(5);
        $this->assertTrue($this->Flame->needBonus()); //ボーナス付与前
        $this->Flame->addBonus(5);
        $this->assertFalse($this->Flame->needBonus());
    }

    /**
     * @test
     */
    public function _ストライクのボーナスは2投分で完了()
    {
        $this->Flame->recordShot(10);
        $this->Flame->addBonus(5);
        $this->assertTrue($this->Flame->needBonus()); //ボーナス付与後①
        $this->Flame->addBonus(5);
        $this->assertFalse($this->Flame->needBonus()); //ボーナス付与後②
    }

これが通るロジックは↓

ロジック修正

Flame.php
    /** @var  int */
    private $bonusCount=0;

    /**
     * @param int $pin
     */
    public function addBonus(int $pin)
    {
        $this->bonus += $pin;
        $this->bonusCount += 1;
    }


    /**
     * @return bool
     */
    public function needBonus(): bool
    {
        if ($this->isSpare()) {
            return $this->bonusCount < 1;
        }

        if ($this->isStrike()) {
            return $this->bonusCount < 2;
        }

        return false;
    }

テスト実行

OK (21 tests, 38 assertions)

ゲームの合算値をFlameから返す($scoreプロパティの排除)

これを

BowlingGameTest.php
    /**
     * @return int [description]
     */
    public function calculateScore(): int
    {
        return $this->score;
    }

こう

BowlingGame.php
    /**
     * @return int [description]
     */
    public function calculateScore(): int
    {
        $total = 0;
        foreach ($this->Flames as $Flame) {
            $total += $Flame->getScore();
        }

        return $total;
    }

テストも通る

OK (21 tests, 38 assertions)

終了

まだ改良できる点はあるものの、もう流れはつかめたし
責務も分担できたし一旦クローズ。

気が向いたら気合の入ったリファウタリングを行ってアップしたい

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0