テストケースからコードを書くとは?
テスト駆動開発(TDD)では、まずテストケース
を書き、そのテストケースを満たすためにコードを実装するという手法を採用します。このアプローチでは、最初に機能を正確に定義し、それを実現するコードを後から書くため、より効率的でバグの少ない開発が可能です。
この記事では、テストケースからコードを書く方法について、具体的な例を通じて説明します。
テストケースを考える際のポイント
テストケースを考える際は、次の点を押さえることが重要です。
- 期待する動作: コードがどのように動作するか、具体的に定義します。
- 入力と出力: どのような入力が与えられ、どのような出力が期待されるかを明確にします。
- 異常系のテスト: 予期しない入力やエラー状態もテストして、堅牢なコードを実現します。
テストケースからコードを実装する流れ
以下に、テストケースからコードを書く具体的な流れを説明します。
- テストケースを作成する:最初に、テストケースを作成します。この時点では、まだ実装が存在しないため、テストは失敗します。
- 最小限のコードを書く:テストケースをパスするために、最小限のコードを実装します。この段階では、複雑なロジックや最適化は不要です。
- テストが通ることを確認する:実装したコードが、すべてのテストケースを通過するか確認します。テストが成功したら、次のステップに進みます。
- リファクタリング:テストが通った後、コードを整理し、読みやすく保守しやすい状態にします。冗長な部分を削除し、コードを最適化します。
具体例: TDDを使ったJavaScript開発
次に、TDDを使用して、シンプルな配列フィルタリング関数を作成する具体例を紹介します。
ステップ1: テストケースを作成する
まず、フィルタリングする関数に対してテストケースを書きます。配列から偶数だけを取り出す関数を実装するとします。
const filterEven = require('./filterEven');
test('filters even numbers from array', () => {
const input = [1, 2, 3, 4, 5];
const output = [2, 4];
expect(filterEven(input)).toEqual(output);
});
test('returns empty array for no even numbers', () => {
const input = [1, 3, 5];
const output = [];
expect(filterEven(input)).toEqual(output);
});
この時点では、filterEven
関数が実装されていないため、テストは失敗します。
ステップ2: 最小限のコードを書く
次に、テストをパスするために、最小限のコードを実装します。ここでは、偶数フィルタリングを実現する関数を定義します。
function filterEven(numbers) {
return numbers.filter(n => n % 2 === 0);
}
module.exports = filterEven;
このコードは、入力配列から偶数だけをフィルタリングし、新しい配列を返します。これでテストケースが通ります。
ステップ3: テストが通ることを確認する
実装したコードがすべてのテストケースを通過するか確認します。この段階で、テストがパスすれば、次のステップに進むことができます。
ステップ4: コードのリファクタリング
最後に、コードのリファクタリングを行います。この例では既にシンプルなコードになっていますが、コードの重複や冗長性を見つけた場合にはここで改善します。
複数のテストケースを考慮する
実際の開発では、さまざまなケースに対応するために、複数のテストケースを考える必要があります。以下に、異常系のテストや例外処理を含めたテストケースを考慮した例を示します。
異常系のテストケース
test('handles null input gracefully', () => {
expect(filterEven(null)).toEqual([]);
});
test('handles undefined input gracefully', () => {
expect(filterEven(undefined)).toEqual([]);
});
このように、異常な入力(nullやundefined)に対しても、正しい動作が確認できるようにテストケースを追加します。
まとめ
テストケースからコードを書く方法は、テスト駆動開発(TDD)の中心的な手法です。まずテストケースを作成し、そのテストを通過させるために最小限のコードを実装し、最後にリファクタリングを行うことで、効率的に高品質なコードを作成することができます。
テストケースを事前に考えることで、コードが期待通りに動作することを確実にし、バグの発生を抑え、メンテナンス性の高いコードを実現できます。