テスト駆動開発 (Test-Driven Development, TDD)

編集

テスト駆動開発 (TDD) は、コードを書く前にテストを記述し、そのテストを満たす形でコードを開発する手法です。この章では、Rubyを用いて初心者にも分かりやすい基本的な考え方から、中級者向けの実践例までを解説します。

TDDの基本原則

編集

TDDは以下の3つのステップで構成されます:

  1. Red (失敗するテストを書く): まず、実装前にテストを記述し、そのテストが失敗することを確認します。
  2. Green (テストを通過する最小限のコードを書く): テストをパスするために、必要最小限のコードを実装します。
  3. Refactor (リファクタリングする): コードを最適化して、可読性や再利用性を向上させます。

TDDのメリット

編集
  • バグの早期発見: テストを事前に記述することで、バグの発生を未然に防げます。
  • 設計の改善: テストを書く過程で、自然とモジュール化や抽象化が進み、設計が洗練されます。
  • 安心感: コード変更後も既存の機能が壊れていないことをテストで確認できます。

TDDの基本例

編集

以下は、TDDを使って簡単な「整数を加算するメソッド」を実装する例です。

ステップ1: 失敗するテストを書く

編集
test_sum.rb
require 'minitest/autorun'

class TestSum < Minitest::Test
  def test_add
    assert_equal 5, add(2, 3)
  end
end

この時点では add メソッドが存在しないため、テストは失敗します。

ステップ2: テストを通過する最小限のコードを書く

編集
sum.rb
def add(a, b)
  a + b
end

テストを再実行すると、成功します。

ステップ3: リファクタリングする

編集

コードがシンプルなためこの例ではリファクタリングは不要ですが、複雑なケースではコードを整理して最適化します。

実践的なTDDのヒント

編集
  • 1つのテストに1つの目的: テストが失敗したとき、原因を特定しやすくなります。
  • 小さなステップで進める: 小さな単位でテストを追加し、少しずつ機能を増やしていきます。
  • テストの命名: テスト名には、意図や期待する結果を明確に記述します(例: test_add_with_negative_numbers)。

TDDの適用範囲

編集

TDDは以下の状況で特に有効です:

  • ユニットテスト: 小さなメソッドやクラスの動作確認。
  • リグレッションテスト: バグの再発防止。
  • 新機能の開発: 要件を明確にしながら実装できます。

中級者向け: モックと依存関係の扱い

編集

TDDを実践する中で、外部システムやデータベースなどの依存関係を扱う場合があります。このような場合には、モック (Mock) を使用することで、依存関係をシミュレートできます。

以下は、モックを使用したテストの例です:

require 'minitest/autorun'
require 'mocha/minitest'

class TestFetchData < Minitest::Test
  def test_fetch_data
    mock_client = mock
    mock_client.stubs(:get_data).returns({ key: 'value' })

    result = fetch_data(mock_client)
    assert_equal({ key: 'value' }, result)
  end
end

def fetch_data(client)
  client.get_data
end

まとめ

編集

テスト駆動開発は、コードの品質を向上させ、安心して開発を進めるための強力な手法です。最初は少し慣れる必要がありますが、繰り返し練習することで自然と効率的に使いこなせるようになります。初心者は小さなステップで始め、中級者はモックやリファクタリングを駆使してさらにTDDを活用してください。