⚒️

PHPUnitでFizzBuzzを題材にTDDを実践してみる

2022/09/05に公開

目次

  1. 背景
  2. TDDとは
  3. 環境構築
  4. TDD実践
  5. まとめ

背景

最近ソフトウェアテストについて勉強し、テスト駆動開発(以後TDD)という言葉と出会いました。

そこでTDDに興味を持ち、『テスト駆動開発』という書籍を読みました。

テストの技術とは少し違うと思いますが、面白そうな開発手法だと思ったため、
今回、TDDを実践してみることで、UnitテストやTDDについて理解を深めたいと思います。

題材にはこちらを参考に初心者でも実践しやすいFizzBuzzを選びました。

言語は私が仕事で使うことが多いPHP、テストライブラリはPHPUnitを使用します。

TDDとは

そもそもTDDとは、Test-Driven Developmentの略で、日本語では「テスト駆動開発」と訳されています。

この言葉を知った時、テストと言うワードからテストの手法だと私は思ったのですが、
テスト駆動開発』を読んで、TDDとはプログラミングの技術、ソフトウェアの開発手法の1つだと私は解釈しています。

具体的にどのような手法かと言うと、テストコードを利用して、次の3つの順序を繰り返すことで開発を進める開発手法です。

  1. 動作しないテストコードを書く
  2. 書いたテストコードが通るコードを書く(どんなに悪いコードでも良い)
  3. 書いたコードをリファクタリングする

より詳しいことを知りたい方は是非、『テスト駆動開発』を読んでください。

環境構築

環境構築にはdocker-composeを使用しました。

過去の私の記事(こちら)を参考にPHPの実行環境を作成します。
今回はコンテナ1つで動作するようにApacheがインストールされているPHPのDockerイメージを使用します。

docker-compose.yml
version: "3"

services:
  php:
    container_name: "php"
    build:
      dockerfile: "./Dockerfile"
    ports:
      - "8080:80"
    volumes:
      - "./src:/var/www/html"
Dockerfile
FROM php:apache-buster

RUN apt-get update
RUN apt-get -y install git zip unzip vim

RUN cd /usr/bin && curl -s http://getcomposer.org/installer | php && ln -s /usr/bin/composer.phar /usr/bin/composer

WORKDIR /var/www/html

composer.jsonにてPHPUnitのインストールを定義します。

src/composer.json
{
    "require-dev": {
        "phpunit/phpunit": "*"
    }
}

コンテナを立ち上げ、PHPUnitをインストールします。

$ docker compose up -d --build

[+] Running 1/1
 ⠿ Container php  Started
 
$ docker exec php composer install
$ docker exec php ./vendor/bin/phpunit --version

PHPUnit 9.5.24 #StandWithUkraine

PHPUnitが正常にインストール出来ました。

src配下にPHPファイルを作成し、TDDの実践に入ります。

$ cd src
$ touch index.php

TDD実践

1. TODOリストの作成

TDDを実践するのに当たって、まずは完成までの工程をTODOリストにしていきます。
各TODOについてTDDのサイクルを回すことで機能を完成させていきます。

私なりに考えたTODOリストは下記の通りです。

  • 入力を受けて返す関数を作成
  • 3が入力されたら、「Fizz」を返す
  • 3の倍数が入力されたら、「Fizz」を返す
  • 5が入力されたら、「Buzz」を返す
  • 5の倍数が入力されたら、「Buzz」を返す
  • 15が入力されたら、「FizzBuzz」を返す
  • 15の倍数が入力されたら、「FizzBuzz」を返す
  • 0が入力されたら、「Zero」を返す
  • 整数以外の値が入力された時、「Not Integer」を返す

まずは元となる入力を受けて返すメソッドを作成します。

src/index.php
<?php

// FizzBuzzを実装するクラス
class FizzBuzz
{
    // テスト対象のメソッド
    public function fizzbuzz ($value)
    {
        return $value;
    }
}

現在のTODOリストがこちらです。

  • 入力を受けて返す関数を作成
  • 3が入力されたら、「Fizz」を返す
  • 3の倍数が入力されたら、「Fizz」を返す
  • 5が入力されたら、「Buzz」を返す
  • 5の倍数が入力されたら、「Buzz」を返す
  • 15が入力されたら、「FizzBuzz」を返す
  • 15の倍数が入力されたら、「FizzBuzz」を返す
  • 0が入力されたら、「Zero」を返す
  • 整数以外の値が入力された時、「Not Integer」を返す

2. テストを書く

このメソッドをテストするためのPHPファイルを作成して、TDDのサイクルを実践していきます。

$ cd src
$ touch FizzBuzzTest.php

まず、3が入力されたら、Fizzを返すというテストを書きます。

src/FizzBuzzTest.php
<?php

use PHPUnit\Framework\TestCase;
require('index.php');

class FizzBuzzTest extends TestCase
{
    /**
     * テスト1
     * 入力:3
     * 想定:Fizzを返す
     */
    public function test3Fizz ()
    {
        // 想定する値
        $expected = "Fizz";

        // 実際の値
        $fb = new FizzBuzz();
        $actual = $fb->fizzbuzz(3);

        // 想定の値と実際の値が一致するかをテスト
        $this->assertSame($expected, $actual);
    }
}

テストコードが出来たので、テストを実行します。

$ docker exec php ./vendor/bin/phpunit FizzBuzzTest.php

PHPUnit 9.5.24 #StandWithUkraine

F                                                                1 / 1 (100%)

Time: 00:00.020, Memory: 4.00 MB

There was 1 failure:

1) FizzBuzzTest::test3Fizz
Failed asserting that 3 matches expected 'Fizz'.

/var/www/html/FizzBuzzTest.php:21

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

想定通り、想定の値と実際の値が異なるため、テストが失敗しました。

3. コードを書く

次にテストが通るコードを書いていきます。

この工程ではとにかくテストが通る最も簡易なコードを書きます。

src/index.php
<?php

// FizzBuzzを実装するクラス
class FizzBuzz
{
    // テスト対象のメソッド
    public function fizzbuzz ($value)
    {
        $result = "Fizz"; // 追加
        return $result;
    }
}

もう一度テストを実行します。

$ docker exec php ./vendor/bin/phpunit FizzBuzzTest.php
PHPUnit 9.5.24 #StandWithUkraine

.                                                                1 / 1 (100%)

Time: 00:00.022, Memory: 4.00 MB

OK (1 test, 1 assertion)

テストが成功しました。

4. リファクタリングする

テストは通りましたが、最も簡易な実装になってしまっているので、
入力が3の場合、Fizzを返すようにリファクタリングしていきます。

src/index.php
<?php

// FizzBuzzを実装するクラス
class FizzBuzz
{
    // テスト対象のメソッド
    public function fizzbuzz ($value)
    {
        $result = ($value === 3) ? "Fizz" : $value; // 書き換え
        return $result;
    }
}

もう一度テストを実行します。

$ docker exec php ./vendor/bin/phpunit FizzBuzzTest.php
PHPUnit 9.5.24 #StandWithUkraine

.                                                                1 / 1 (100%)

Time: 00:00.034, Memory: 4.00 MB

OK (1 test, 1 assertion)

テストが成功しました。
これでリファクタリングを行なっても機能が壊れていないことを確認出来ました。

現在のTODOリストがこちらです。

  • 入力を受けて返す関数を作成
  • 3が入力されたら、「Fizz」を返す
  • 3の倍数が入力されたら、「Fizz」を返す
  • 5が入力されたら、「Buzz」を返す
  • 5の倍数が入力されたら、「Buzz」を返す
  • 15が入力されたら、「FizzBuzz」を返す
  • 15の倍数が入力されたら、「FizzBuzz」を返す
  • 0が入力されたら、「Zero」を返す
  • 整数以外の値が入力された時、「Not Integer」を返す

5. 繰り返す

テストを書く、テストが通るコードを書く、リファクタリングをするというサイクルを繰り返していきます。

ここからは長いので読み飛ばし推奨。

  • 入力を受けて返す関数を作成
  • 3が入力されたら、「Fizz」を返す
  • 3の倍数が入力されたら、「Fizz」を返す ←こちらを実装
  • 5が入力されたら、「Buzz」を返す
  • 5の倍数が入力されたら、「Buzz」を返す
  • 15が入力されたら、「FizzBuzz」を返す
  • 15の倍数が入力されたら、「FizzBuzz」を返す
  • 0が入力されたら、「Zero」を返す
  • 整数以外の値が入力された時、「Not Integer」を返す
src/FizzBuzzTest.php
<?php

use PHPUnit\Framework\TestCase;
require('index.php');

class FizzBuzzTest extends TestCase
{
    /**
     * テスト1
     * 入力:3の倍数
     * 想定:Fizzを返す
     */
    public function test3Fizz ()
    {
        // 想定する値
        $expected = "Fizz";

        // 検証値
        $fb = new FizzBuzz();
        $actual1 = $fb->fizzbuzz(3);
        $actual2 = $fb->fizzbuzz(4);
        $actual3 = $fb->fizzbuzz(6);
        $actual4 = $fb->fizzbuzz(9);
        $actual5 = $fb->fizzbuzz(11);

        // 想定の値と検証値が一致するかをテスト
        $this->assertSame($expected, $actual1);
        $this->assertNotSame($expected, $actual2);
        $this->assertSame($expected, $actual3);
        $this->assertSame($expected, $actual4);
        $this->assertNotSame($expected, $actual5);
    }
}
$ docker exec php ./vendor/bin/phpunit FizzBuzzTest.php
PHPUnit 9.5.24 #StandWithUkraine

F                                                                1 / 1 (100%)

Time: 00:00.027, Memory: 4.00 MB

There was 1 failure:

1) FizzBuzzTest::test3Fizz
Failed asserting that 6 is identical to 'Fizz'.

/var/www/html/FizzBuzzTest.php:29

FAILURES!
Tests: 1, Assertions: 3, Failures: 1.
src/index.php
<?php

// FizzBuzzを実装するクラス
class FizzBuzz
{
    // テスト対象のメソッド
    public function fizzbuzz ($value)
    {
        $result = ($value % 3 === 0) ? "Fizz" : $value; // 書き換え
        return $result;
    }
}
$ docker exec php ./vendor/bin/phpunit FizzBuzzTest.php
PHPUnit 9.5.24 #StandWithUkraine

.                                                                1 / 1 (100%)

Time: 00:00.018, Memory: 4.00 MB

OK (1 test, 5 assertions)
  • 入力を受けて返す関数を作成
  • 3が入力されたら、「Fizz」を返す
  • 3の倍数が入力されたら、「Fizz」を返す ←実装完了
  • 5が入力されたら、「Buzz」を返す ←こちらを実装
  • 5の倍数が入力されたら、「Buzz」を返す
  • 15が入力されたら、「FizzBuzz」を返す
  • 15の倍数が入力されたら、「FizzBuzz」を返す
  • 0が入力されたら、「Zero」を返す
  • 整数以外の値が入力された時、「Not Integer」を返す
src/FizzBuzzTest.php
~省略~
    /**
     * テスト2
     * 入力:5
     * 想定:Buzzを返す
     */
    public function test5Buzz ()
    {
        // 想定する値
        $expected = "Buzz";

        // 検証値
        $fb = new FizzBuzz();
        $actual1 = $fb->fizzbuzz(5);

        // 想定の値と検証値が一致するかをテスト
        $this->assertSame($expected, $actual1);
    }
~省略~
$ docker exec php ./vendor/bin/phpunit FizzBuzzTest.php
PHPUnit 9.5.24 #StandWithUkraine

.F                                                               2 / 2 (100%)

Time: 00:00.021, Memory: 4.00 MB

There was 1 failure:

1) FizzBuzzTest::test5Buzz
Failed asserting that 5 is identical to 'Buzz'.

/var/www/html/FizzBuzzTest.php:49

FAILURES!
Tests: 2, Assertions: 6, Failures: 1.
src/index.php
<?php

// FizzBuzzを実装するクラス
class FizzBuzz
{
    // テスト対象のメソッド
    public function fizzbuzz ($value)
    {
        $result = ($value % 3 === 0) ? "Fizz" 
            : (($value === 5) ? "Buzz" : $value); // 追加
        return $result;
    }
}
$ docker exec php ./vendor/bin/phpunit FizzBuzzTest.php
PHPUnit 9.5.24 #StandWithUkraine

..                                                               2 / 2 (100%)

Time: 00:00.018, Memory: 4.00 MB

OK (2 tests, 6 assertions)
  • 入力を受けて返す関数を作成
  • 3が入力されたら、「Fizz」を返す
  • 3の倍数が入力されたら、「Fizz」を返す
  • 5が入力されたら、「Buzz」を返す ←実装完了
  • 5の倍数が入力されたら、「Buzz」を返す ←こちらを実装
  • 15が入力されたら、「FizzBuzz」を返す
  • 15の倍数が入力されたら、「FizzBuzz」を返す
  • 0が入力されたら、「Zero」を返す
  • 整数以外の値が入力された時、「Not Integer」を返す
src/FizzBuzzTest.php
~省略~
    /**
     * テスト2
     * 入力:5の倍数
     * 想定:Buzzを返す
     */
    public function test5Buzz ()
    {
        // 想定する値
        $expected = "Buzz";

        // 検証値
        $fb = new FizzBuzz();
        $actual1 = $fb->fizzbuzz(5);
        $actual2 = $fb->fizzbuzz(6);
        $actual3 = $fb->fizzbuzz(10);
        $actual4 = $fb->fizzbuzz(13);
        $actual5 = $fb->fizzbuzz(17);
        $actual6 = $fb->fizzbuzz(20);

        // 想定の値と検証値が一致するかをテスト
        $this->assertSame($expected, $actual1);
        $this->assertNotSame($expected, $actual2);
        $this->assertSame($expected, $actual3);
        $this->assertNotSame($expected, $actual4);
        $this->assertNotSame($expected, $actual5);
        $this->assertSame($expected, $actual6);
    }
~省略~
$ docker exec php ./vendor/bin/phpunit FizzBuzzTest.php
PHPUnit 9.5.24 #StandWithUkraine

.F                                                               2 / 2 (100%)

Time: 00:00.021, Memory: 4.00 MB

There was 1 failure:

1) FizzBuzzTest::test5Buzz
Failed asserting that 10 is identical to 'Buzz'.

/var/www/html/FizzBuzzTest.php:56

FAILURES!
Tests: 2, Assertions: 8, Failures: 1.
src/index.php
<?php

// FizzBuzzを実装するクラス
class FizzBuzz
{
    // テスト対象のメソッド
    public function fizzbuzz ($value)
    {
        $result = ($value % 3 === 0) ? "Fizz" 
            : (($value % 5 === 0) ? "Buzz" : $value); // 書き換え
        return $result;
    }
}

$ docker exec php ./vendor/bin/phpunit FizzBuzzTest.php
PHPUnit 9.5.24 #StandWithUkraine

..                                                               2 / 2 (100%)

Time: 00:00.018, Memory: 4.00 MB

OK (2 tests, 11 assertions)
  • 入力を受けて返す関数を作成
  • 3が入力されたら、Fizzを返す
  • 3の倍数が入力されたら、Fizzを返す
  • 5が入力されたら、Buzzを返す
  • 5の倍数が入力されたら、Buzzを返す ←実装完了
  • 15が入力されたら、FizzBuzzを返す ←こちらを実装
  • 15の倍数が入力されたら、FizzBuzzを返す
  • 0が入力されたら、「Zero」という独自のエラーを返す
  • 整数以外の値が入力された時、「Not Integer」という独自エラーを返す
src/FizzBuzzTest.php
~省略~
    /**
     * テスト3
     * 入力:15
     * 想定:FizzBuzzを返す
     */
    public function test15FizzBuzz ()
    {
        // 想定する値
        $expected = "FizzBuzz";

        // 検証値
        $fb = new FizzBuzz();
        $actual1 = $fb->fizzbuzz(15);

        // 想定の値と検証値が一致するかをテスト
        $this->assertSame($expected, $actual1);
    }
~省略~
$ docker exec php ./vendor/bin/phpunit FizzBuzzTest.php
PHPUnit 9.5.24 #StandWithUkraine

..F                                                              3 / 3 (100%)

Time: 00:00.023, Memory: 4.00 MB

There was 1 failure:

1) FizzBuzzTest::test15FizzBuzz
Failed asserting that two strings are identical.
--- Expected
+++ Actual
@@ @@
-'FizzBuzz'
+'Fizz'

/var/www/html/FizzBuzzTest.php:77

FAILURES!
Tests: 3, Assertions: 12, Failures: 1.
src/index.php
<?php

// FizzBuzzを実装するクラス
class FizzBuzz
{
    // テスト対象のメソッド
    public function fizzbuzz ($value)
    {
        $result = ($value === 15) ? "FizzBuzz" // 追加
            : (($value % 3 === 0) ? "Fizz" 
            : (($value % 5 === 0) ? "Buzz" 
            : $value));
        return $result;
    }
}
$ docker exec php ./vendor/bin/phpunit FizzBuzzTest.php
PHPUnit 9.5.24 #StandWithUkraine

...                                                              3 / 3 (100%)

Time: 00:00.018, Memory: 4.00 MB

OK (3 tests, 12 assertions)
  • 入力を受けて返す関数を作成
  • 3が入力されたら、「Fizz」を返す
  • 3の倍数が入力されたら、「Fizz」を返す
  • 5が入力されたら、「Buzz」を返す
  • 5の倍数が入力されたら、「Buzz」を返す
  • 15が入力されたら、「FizzBuzz」を返す ←実装完了
  • 15の倍数が入力されたら、「FizzBuzz」を返す ←こちらを実装
  • 0が入力されたら、「Zero」を返す
  • 整数以外の値が入力された時、「Not Integer」を返す
src/FizzBuzzTest.php
~省略~
    /**
     * テスト3
     * 入力:15の倍数
     * 想定:FizzBuzzを返す
     */
    public function test15FizzBuzz ()
    {
        // 想定する値
        $expected = "FizzBuzz";

        // 検証値
        $fb = new FizzBuzz();
        $actual1 = $fb->fizzbuzz(5);
        $actual2 = $fb->fizzbuzz(3);
        $actual3 = $fb->fizzbuzz(15);
        $actual4 = $fb->fizzbuzz(18);
        $actual5 = $fb->fizzbuzz(29);
        $actual6 = $fb->fizzbuzz(30);
        $actual7 = $fb->fizzbuzz(75);

        // 想定の値と検証値が一致するかをテスト
        $this->assertNotSame($expected, $actual1);
        $this->assertNotSame($expected, $actual2);
        $this->assertSame($expected, $actual3);
        $this->assertNotSame($expected, $actual4);
        $this->assertNotSame($expected, $actual5);
        $this->assertSame($expected, $actual6);
        $this->assertSame($expected, $actual7);
    }
~省略~
$ docker exec php ./vendor/bin/phpunit FizzBuzzTest.php
PHPUnit 9.5.24 #StandWithUkraine

..F                                                              3 / 3 (100%)

Time: 00:00.034, Memory: 4.00 MB

There was 1 failure:

1) FizzBuzzTest::test15FizzBuzz
Failed asserting that two strings are identical.
--- Expected
+++ Actual
@@ @@
-'FizzBuzz'
+'Fizz'

/var/www/html/FizzBuzzTest.php:88

FAILURES!
Tests: 3, Assertions: 17, Failures: 1.
src/index.php
<?php

// FizzBuzzを実装するクラス
class FizzBuzz
{
    // テスト対象のメソッド
    public function fizzbuzz ($value)
    {
        $result = ($value % 15 === 0) ? "FizzBuzz" // 書き換え
            : (($value % 3 === 0) ? "Fizz" 
            : (($value % 5 === 0) ? "Buzz" 
            : $value));
        return $result;
    }
}
$ docker exec php ./vendor/bin/phpunit FizzBuzzTest.php
PHPUnit 9.5.24 #StandWithUkraine

...                                                              3 / 3 (100%)

Time: 00:00.018, Memory: 4.00 MB

OK (3 tests, 18 assertions)
  • 入力を受けて返す関数を作成
  • 3が入力されたら、「Fizz」を返す
  • 3の倍数が入力されたら、「Fizz」を返す
  • 5が入力されたら、「Buzz」を返す
  • 5の倍数が入力されたら、「Buzz」を返す
  • 15が入力されたら、「FizzBuzz」を返す
  • 15の倍数が入力されたら、「FizzBuzz」を返す ←実装完了
  • 0が入力されたら、「Zero」を返す ←こちらを実装
  • 整数以外の値が入力された時、「Not Integer」を返す
src/FizzBuzzTest.php
~省略~
    /**
     * テスト4
     * 入力:0
     * 想定:Zeroを返す
     */
    public function testZero ()
    {
        // 想定する値
        $expected = "Zero";

        // 検証値
        $fb = new FizzBuzz();
        $actual1 = $fb->fizzbuzz(0);
        $actual2 = $fb->fizzbuzz(3);
        $actual3 = $fb->fizzbuzz(5);
        $actual4 = $fb->fizzbuzz(15);
        $actual5 = $fb->fizzbuzz(26);

        // 想定の値と検証値が一致するかをテスト
        $this->assertSame($expected, $actual1);
        $this->assertNotSame($expected, $actual2);
        $this->assertNotSame($expected, $actual3);
        $this->assertNotSame($expected, $actual4);
        $this->assertNotSame($expected, $actual5);
    }
~省略~
$ docker exec php ./vendor/bin/phpunit FizzBuzzTest.php
PHPUnit 9.5.24 #StandWithUkraine

...F                                                             4 / 4 (100%)

Time: 00:00.024, Memory: 4.00 MB

There was 1 failure:

1) FizzBuzzTest::testZero
Failed asserting that two strings are identical.
--- Expected
+++ Actual
@@ @@
-'Zero'
+'FizzBuzz'

/var/www/html/FizzBuzzTest.php:111

FAILURES!
Tests: 4, Assertions: 19, Failures: 1.
src/index.php
<?php

// FizzBuzzを実装するクラス
class FizzBuzz
{
    // テスト対象のメソッド
    public function fizzbuzz ($value)
    {
        $result = ($value === 0) ? "Zero" // 追加
            : (($value % 15 === 0) ? "FizzBuzz" 
            : (($value % 3 === 0) ? "Fizz" 
            : (($value % 5 === 0) ? "Buzz" 
            : $value)));
        return $result;
    }
}
$ docker exec php ./vendor/bin/phpunit FizzBuzzTest.php
PHPUnit 9.5.24 #StandWithUkraine

....                                                             4 / 4 (100%)

Time: 00:00.023, Memory: 4.00 MB

OK (4 tests, 23 assertions)
  • 入力を受けて返す関数を作成
  • 3が入力されたら、「Fizz」を返す
  • 3の倍数が入力されたら、「Fizz」を返す
  • 5が入力されたら、「Buzz」を返す
  • 5の倍数が入力されたら、「Buzz」を返す
  • 15が入力されたら、「FizzBuzz」を返す
  • 15の倍数が入力されたら、「FizzBuzz」を返す
  • 0が入力されたら、「Zero」を返す ←実装完了
  • 整数以外の値が入力された時、「Not Integer」を返す ←こちらを実装
src/FizzBuzzTest.php
~省略~
    /**
     * テスト5
     * 入力1:任意の文字列
     * 入力2:任意の真偽値
     * 入力3:任意の少数
     * 想定:Not Integerを返す
     */
    public function testNotInteger ()
    {
        // 想定する値
        $expected = "Not Integer";

        // 検証値
        $fb = new FizzBuzz();
        $actual1 = $fb->fizzbuzz("Hello World");
        $actual2 = $fb->fizzbuzz(true);
        $actual3 = $fb->fizzbuzz(1.6);
        $actual4 = $fb->fizzbuzz(4);

        // 想定の値と検証値が一致するかをテスト
        $this->assertSame($expected, $actual1);
        $this->assertSame($expected, $actual2);
        $this->assertSame($expected, $actual3);
        $this->assertNotSame($expected, $actual4);
    }
~省略~
$ docker exec php ./vendor/bin/phpunit FizzBuzzTest.php
PHPUnit 9.5.24 #StandWithUkraine

....E                                                            5 / 5 (100%)

Time: 00:00.029, Memory: 4.00 MB

There was 1 error:

1) FizzBuzzTest::testNotInteger
TypeError: Unsupported operand types: string % int

/var/www/html/index.php:10
/var/www/html/FizzBuzzTest.php:132

ERRORS!
Tests: 5, Assertions: 23, Errors: 1.
src/index.php
<?php

// FizzBuzzを実装するクラス
class FizzBuzz
{
    // テスト対象のメソッド
    public function fizzbuzz ($value)
    {
        $result = (gettype($value) !== "integer") ? "Not Integer" // 追加
            : (($value === 0) ? "Zero" 
            : (($value % 15 === 0) ? "FizzBuzz" 
            : (($value % 3 === 0) ? "Fizz" 
            : (($value % 5 === 0) ? "Buzz" 
            : $value))));
        return $result;
    }
}
$ docker exec php ./vendor/bin/phpunit FizzBuzzTest.php
PHPUnit 9.5.24 #StandWithUkraine

.....                                                            5 / 5 (100%)

Time: 00:00.019, Memory: 4.00 MB

OK (5 tests, 27 assertions)
  • 入力を受けて返す関数を作成
  • 3が入力されたら、「Fizz」を返す
  • 3の倍数が入力されたら、「Fizz」を返す
  • 5が入力されたら、「Buzz」を返す
  • 5の倍数が入力されたら、「Buzz」を返す
  • 15が入力されたら、「FizzBuzz」を返す
  • 15の倍数が入力されたら、「FizzBuzz」を返す
  • 0が入力されたら、「Zero」を返す
  • 整数以外の値が入力された時、「Not Integer」を返す ←実装完了

全てのTODOリストの実装が完了しました。

最後にもう一度リファクタリングを行なって、FizzBuzzの実装は完了としたいと思います。

src/index.php
<?php

// FizzBuzzを実装するクラス
class FizzBuzz
{
    // テスト対象のメソッド
    public function fizzbuzz ($value)
    {
        return (gettype($value) !== "integer") ? "Not Integer"
            : (($value === 0) ? "Zero" 
            : (($value % 15 === 0) ? "FizzBuzz" 
            : (($value % 3 === 0) ? "Fizz" 
            : (($value % 5 === 0) ? "Buzz" 
            : $value
        ))));
    }
}

$ docker exec php ./vendor/bin/phpunit FizzBuzzTest.php
PHPUnit 9.5.24 #StandWithUkraine

.....                                                            5 / 5 (100%)

Time: 00:00.018, Memory: 4.00 MB

OK (5 tests, 27 assertions)

これでTDDの実践が完了しました。

まとめ

実際にTDDを実践してみて、TODOリストの作成が非常に重要だと感じました。

粒度が細かいと実装に関する心理的安全性は増しますが、
私の性格的に一気に作りたいという焦りの気持ちが出てきました。

こちらに関しては慣れや心理的安全性を重視するべきかも知れませんが、
人によって適切な粒度があるのではないでしょうか。

また、TDDはプログラミング技法ですが、単体テストに関する正しい知識が必要だと感じました。

今回使用したコードのリポジトリはこちらになります。

Discussion