FizzBuzz問題でユニットテストを書いてみる

CakePHP2系の環境でユニットテストを試したかったので、FizzBuzz問題でユニットテストを書いてみました。

# FizzBuzz問題とは
1から数字を数えていき、
3の倍数のときは「Fizz」
5の倍数のときは「Buzz」
3と5の倍数のときは「FizzBuzz」
と答えていく言葉遊びゲームです。

```
1, 2, Fizz, 4, Buzz, Fizz, 7, 8, Fizz, Buzz, 11, Fizz, 13, 14, FizzBuzz, 16, 17, Fizz, 19, Buzz ...
```

# 環境
CentOS7
MariaDB 5.5.60
PHP 7.2.9
CakePHP 2.10.11
PHPUnit 3.7.38

ドキュメントルート：/var/www/html/
CakePHPのファイル：/var/www/html/cakephp/

Vendor配下にPHPUnitのpharファイルを置けば、CakePHPでPHPUnitが動きます。

```
cd /var/www/html/cakephp/app/Vendor
wget https://phar.phpunit.de/phpunit-3.7.38.phar -O phpunit.phar
```

# モデルの作成

FizzBuzzのプログラムを書いたモデルを作成します。

```php:app/Model/FizzBuzz.php
<?php
class FizzBuzz extends AppModel
{
    public function execute($number)
    {
        if ($number % 3 === 0 && $number % 5 === 0) {
            return 'FizzBuzz';
        }
        if ($number % 3 === 0) {
            return 'Fizz';
        }
        if ($number % 5 === 0) {
            return 'Buzz';
        }
        return $number;
    }
}
?>
```

# 失敗するテストの作成

試しにわざと失敗するテストケースを書いてみます。

```php:app/Test/Case/Model/FizzBuzzTest.php
<?php
App::uses('FizzBuzz', 'Model');

class FizzBuzzTest extends CakeTestCase
{
    public function setUp()
    {
        $this->FizzBuzz = ClassRegistry::init('FizzBuzz');
    }

    public function test_fizz()
    {
        // assertSameで値が一致しなければテストは失敗する
        $this->assertSame('Fizz', $this->FizzBuzz->execute(5));
    }
}
?>
```

テストを実行します。

```
$ sudo /var/www/html/cakephp/app/Console/cake test app Model/FizzBuzz
```

assertSameの値が一致しなかったので、テストは失敗しました。

```
There was 1 failure:
1) FizzBuzzTest::test_fizz
Failed asserting that two strings are identical.
--- Expected
+++ Actual
@@ @@
-Fizz
+Buzz

:

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

# 成功するテストの作成

次に成功するテストケースを書いてみます。

```php:app/Test/Case/Model/FizzBuzzTest.php
<?php
App::uses('FizzBuzz', 'Model');

class FizzBuzzTest extends CakeTestCase
{
    public function setUp()
    {
        $this->FizzBuzz = ClassRegistry::init('FizzBuzz');
    }

    /**
     * 3の倍数のときはFizzを返す
     */
    public function test_fizz()
    {
        $this->assertSame('Fizz', $this->FizzBuzz->execute(3));
        $this->assertSame('Fizz', $this->FizzBuzz->execute(6));
        $this->assertSame('Fizz', $this->FizzBuzz->execute(9));
    }

    /**
     * 5の倍数のときはBuzzを返す
     */
    public function test_buzz()
    {
        $this->assertSame('Buzz', $this->FizzBuzz->execute(5));
        $this->assertSame('Buzz', $this->FizzBuzz->execute(10));
        $this->assertSame('Buzz', $this->FizzBuzz->execute(20));
    }

    /**
     * 3と5の倍数のときはFizzBuzzを返す
     */
    public function test_fizzBuzz()
    {
        $this->assertSame('FizzBuzz', $this->FizzBuzz->execute(15));
        $this->assertSame('FizzBuzz', $this->FizzBuzz->execute(30));
        $this->assertSame('FizzBuzz', $this->FizzBuzz->execute(45));
    }

    /**
     * それ以外のときは数値を返す
     */
    public function test_number()
    {
        $this->assertSame(1, $this->FizzBuzz->execute(1));
        $this->assertSame(11, $this->FizzBuzz->execute(11));
        $this->assertSame(22, $this->FizzBuzz->execute(22));
    }
}
```
テストを実行します。

```
$ sudo /var/www/html/cakephp/app/Console/cake test app Model/FizzBuzz
```
OKと出たのでテストに成功しました。

```

Time: 91 ms, Memory: 12.00Mb

OK (4 tests, 12 assertions)
```

# 終わりに

このようにFizzBuzzの
・3の倍数のときは「Fizz」を返す
・5の倍数のときは「Buzz」を返す
・3と5の倍数のときは「FizzBuzz」を返す
・それ以外のときは数値を返す
という要件に対してテストケースを作成しました。

完璧にテストするのは難しいので1つのテストケースに3つのアサーションを書いています。

以上で終わりです。