初投稿記事です。自分の備忘録的なものにしたいため、雑な記事になる予定です。
TDDとは
Test-Driven Development(TDD)は、ソフトウェア開発の手法の一つ。TDDでは、まずテストを書き、このテストは、開発者が実装したい機能や振る舞いを定義し、その機能が正しく動作するかどうかを確認するためのもの。その後、テストが失敗することを確認。
テスト工程
1. 単体テスト
システムの個々のコンポーネントやモジュールが正しく機能することを確認するためのテスト
const add = (arg1: number, arg2: number) => {
return arg1 + arg2;
}
このような関数単位、またはクラス単位で作成するテスト
describe("add", () => {
it("正しく足し算が行われるか", () => {
expect(add(1, 2)).toBe(5);
})
})
2. 結合テスト
機能を組み合わせて正しく動作するのか検証するテスト。front側だと、フォームのテストとかaxiosをmockして、返した値がちゃんと表示されているか。
3. 総合テスト
システム開発における工程のひとつであり、システム開発で行われるテスト方法の一つ
(例) Cypress
テスト種別
ホワイトボックステスト
ソフトウェアの内部構造に着目したテスト。単体テストが主な工程となる。
・制御フローテスト
制御フローは、1つの処理に対してソフトウェアがどのように動くかをフローチャートと呼ばれる図にしたもの。if文の条件式や繰り返しのロジックによって指定された処理の流れを図示。
実施方法の例として、
-
カバレッジ基準を決める
制御フローテストで着目する要素を、以下から選択。- 命令文(ステートメントカバレッジ)
- 分岐した経路(ブランチカバレッジ)
- 条件(複合条件カバレッジ)
-
カバレッジ基準を網羅する経路を抽出する
フローチャートを見ながら、カバレッジ基準をすべて通るフローチャート上の経路を決定。 -
抽出した経路を通るようにテストを行う
抽出した経路を通る入力値を指定してモジュールを動作させ、テストする。
カバレッジについて
テスト対象のプログラムがどこまでテスト実施されたのかの割合。以下のような関数のテストがあるとする。
describe("FizzBuzz", () => {
it("正しいFizzBuzzが返るか", () => {
expect(FizzBuzz(true, true)).toBe("FizzBuzz");
expect(FizzBuzz(true, false)).toBe("Fizz");
expect(FizzBuzz(false, true)).toBe("Buzz");
})
})
このテストのカバレッジは、FizzBuzz(false, false)
が行われていないので、75%である。一般に、カバレッジの確保とテストの工数は、トレードオフである。
・データフローテスト
データフローとは、モジュール内で使用されるデータや変数処理の流れのこと。特に、変数データが「定義」「使用(参照)」「消滅」するような処理を指す。データに着目して意図した順序で正しく処理されるか、無駄なデータ処理をしていないかなどを確認する。
ブラックボックステスト
確認する条件や入出力値の洗い出し、膨大なテスト項目を効率的に絞り込みをするためにさまざまなテスト技法を利用。
・同値分割法
同値領域から代表値を実行するテストケ-スを設計すること。成人かどうかを判別システムがあるとする。
このように、0歳から19歳からと、20歳からのグループに分けて代表値を決める。
・境界値分析
同値クラスの両端にあたる境界値を基にしてテストを行う技法。
以上の通り、境界値である19と20でテストし、また0についてもテストを行う。
テスト設計の注意点
1. 殺虫剤のパラドックス
同じ殺虫剤ばかり使っていると、その耐性を持った個体が現れるというところから、同じテストを何度も繰り返すと、最終的にはそのテストでは新しい欠陥を見つけられなくなるというパラドックス。改定したり新規にテストを作成したりする必要がある。
2. 異常系テスト
正常系のテストばかり書くのではなく、例外処理が適切に行われるか異常系のテストを必ず盛り込むべきである。
まとめ
テストについての備忘録まとめました。TDDによる開発は、自身のコードに自身が持てる、リファクタリングがしやすい、保守性がある、等々メリットも多いので、明日からTDDは、いかかがでしょうか。