【TDD初心者】テストが好きなだけの実務未経験エンジニアがTDDを理解する

IT

はじめ

ソフトウェアテストが大好きな24卒エンジニアです。先日読んだ以下の書籍

こちらでTDDことテスト駆動開発がどんなものか理解できたので今回はそれを整理します。実際にPHPのコードを使って、どんなものか体験してみようと思います。

テスト駆動開発の位置付け

TDD(テスト駆動開発)は、「開発」の技法のことを指します。一方で単体テストは、「テスト」の技法のことを指します。

例えば、このコード…

function saturate(int $value, int $minValue, int $maxValue):int
{
   return min(max($value, $minValue), $maxValue);
}

もし、saturate関数が動作不具合になったとき

  • saturateのコードの記述にバグがあるか
  • max or min関数のどちらかにバグがあるか

この2つのどちらかを疑います。ソフトウェアの不具合は、幅広い下位構造の組み合わせでできています。

テスト駆動開発のメリット・デメリット

メリット

たくさん考えば出ると思いますが、2つ上げます

  • バグがある段階で発見できるため、後の負担が軽減されます。手戻りが少ないことは非常に良いですね
  • テストコードを記述するとき、要件を理解しないと書くことが困難です。テストをはじめに書くことで、仕様ってこんな感じなのか!という理解ができます

デメリット

ここでも2つ例を挙げて考えます

  • 先に実装しちゃうぜ!という感じで開発してきた人にとって習得するのに時間がかかります。初期段階がめちゃくちゃ大変です
  • 長期的な目線を考慮すると保守に時間がかかります。修正作業にも時間がかかる可能性があるので考えておきたいですね

テスト駆動開発をするための準備をする

phpのパッケージマネージャComposerを使って、PHPUnitをインストールします。

$ composer require --dev phpunit/phpunit

コマンドを入力すると、vendor/binディレクトリにphpunitコマンドが追加されます。

※ 本、記事ではテスト駆動開発がどういうものなのかに触れるため、具体的なインストール手順は割愛します。

簡単なテストコードを書いてみる

最初にメソッドを足すのではなく、最も簡単なテストケースを書きます。

    namespace FizzBuzz\Core;
    use PHPUnit\Framework\TestCase;
    
    class NumberConverterTest extends TestCase
    {
        public function testConvert(): void
        {
            $fizzbuzz = new NumberConverter();
            $this->assertEquals("1", fizzBuzz->convert(1)); 
        }
    }
    class NumberConverter
    {
     // 引数の型と値はこんな感じになりそうかなくらいで記述します
      public function convert(int $n): string
      {
        return ""
      }
    }
    class NumberConverter
    {
      public function convert(int $n): string
      {
        return "1" // "1"かどうかかを知りたい!
      }
    }
    namespace FizzBuzz\Core;
    use PHPUnit\Framework\TestCase;
    
    class NumberConverterTest extends TestCase
    {
        public function testConvert(): void
        {
            $fizzbuzz = new NumberConverter();
            $this->assertEquals("1", fizzBuzz->convert(1));
            $this->assertEquals("2", fizzBuzz->convert(2)); // 追加した
        }
    }
    class NumberConverter
    {
      public function convert(int $n): string
      {
        return (string)$n;
      }
    }
    class NumberConverterTest extends TestCase
    {
        public function testConvert(): void
        {
            $fizzbuzz = new NumberConverter();
            $this->assertEquals("1", fizzBuzz->convert(1));
            $this->assertEquals("2", fizzBuzz->convert(2));
            $this->assertEquals("Fizz", fizzBuzz->convert(3)); // 追加した
        }
    }
    class NumberConverter
    {
         public function convert(int $n): string
         {
             if($n == 3){
               return "Fizz";
    
             } else {
               return (string)$n;
             
          }
         }
    }

    上記のような流れで、少しずつコードを記述して進めていきます。

    テストファースト

    • テストを追加→失敗確認→最小限の実装→成功

    このサイクルを繰り返すのがテスト駆動開発の流れです。

    kei
    kei

    実装よりも、テストを最初に書いていくのがテスト駆動開発の鉄則のようです。

    おわりに

    PHPを例に取り上げ、テスト駆動開発がどういうものかを見ていきました。

    テストファーストでコードを少しずつ記述していく開発は、チームでも個人でも進めやすい気がします。ただ慣れるのには時間がかかりそうだなとも思いました。

    テスト駆動開発の概要とは?メリット・デメリット・注意点などを解説!|ITトレンド
    テスト駆動開発とはどのようなソフトウェア開発方法なのでしょうか。テストファーストな方法と聞いて、非実用的だと感じる人も多...

    コメント

    タイトルとURLをコピーしました