🦄

[テスト] 今よりも単体テストを良くする考え方

2024/09/17に公開

はじめに

エンジニアとして初めて入社したPJでテスターとして2年間活動しました。
そのPJでテストについての概念等を理解しました。
しかし、現在のPJでいざテストの文化を1から構築する時に色々分からないことがあった為、
下記書籍で単体テストについて学習しました。
その内容を記録します。

1. 網羅率(coverage)のみを強く意識しない

テストパターンが十分であるかの指標の為に網羅率(coverage)を活用します。
しかし、網羅率(coverage)を強く意識すると逆に開発効率が悪くなり、
いつまでたってもリリースができない悪循環になる可能性があります。

例えば、下記コードに対して入力値を5として返り値がtrueであることを確認するテストパターンの場合
もちろん、網羅率は50%になります。(2,3行目を通過したため)

// 単純な分岐処理
const isGreaterThanOrEqualToFive = (value: number): boolean => {
  if (value >= 5)
    return true;
  else
    return false;
}

しかし、
下記コードに対して同様なテストパターンの場合、網羅率は100%になります。(if分岐を省略して1行の為)

// if文を使わずにシンプル
const isGreaterThanOrEqualToFive = (value: number): boolean => value >= 5;

網羅率が意味がないのか?と考えるのではなく、網羅率が低すぎる状態を回避する事を意識する
さらに、分岐網羅率(branch coverage)で考える網羅率より正確に計測する事が出来る

2. AAAパターンでテストコードを実装する

下記テストコードのようにすべてのテストケースに対して統一された構成にする

// add関数のテスト
test('AAAパターンでテストコードを実装する', () => {
  // 準備(Arrange)
  const arg01 = 1
  const arg02 = 2
  const expectedValue = 3

  // 実行(Act)
  const result = sut.add(arg01, arg02)

  // 確認(Assert)
  expect(result).toBe(expectedValue);
});

3. テスト対象プログラムは、sutと定義する

例えば、インポート時にasを使って定義する

import * as sut from './math';

// 実行(Act)
const result = sut.add(arg01, arg02)

4. テスト・メソッド名は、非開発者でも名称にする

例えば、下記様なテストケースの場合

  • 不正な日付がどんな不正なのか曖昧な為、過去の日付とわかりやすい言葉に変換したり
  • ~だと見なされるべきも曖昧な表現を避けて、~であると変換する
- test('不正な日付が指定された配達は不正だと見なされるべきである', () => {})
+ test('過去の日付が指定された配達は不正である', () => {})

※ 日本語でテストパターンが書けない場合は、ChatGTPなどのAIを活用して英語に翻訳するのもあり

5. テストケースの作成は、ブラックボックステストで考える

ホワイトボックステストだとソースコードの細部まで配慮する事が可能のため、
ブラックボックステストでは検出する事が出来ない不具合を検出する事が可能である
しかし、

そのため、
保守コストを抑えるためにも、ブラックボックステストでテストケースを作成し、
壊れないテストコードにする

では、ホワイトボックステストの活用方法は、
分岐網羅率(branch coverage)の向上のために活用する

TH リファクタリングへの耐性 不具合の検出率
ホワイトボックステスト 劣っている 優れている
ブラックボックステスト 優れている 劣っている

6. 良い単体テストの定義とは

1. 後退(regression)に対する保護

  • テストをする事でデグレの存在をいかに検出できるのかを示す性質である
  • 開発者が開発したソースコードだけではなく、使用しているライブラリーやフレームワークが多いほど効果的である

2. リファクタリングへの耐性

  • いかに偽陽性を生み出すことなく、リファクタリングを行えるのかを示す性質である
    ※テスト対象プログラムは、問題ないにもかかわらず嘘のテストを通知すること

3. 迅速なフィードバック

  • テストの実行時間をどのぐらい短くなるのかに影響する性質である

4. 保守のしやすさ

  • 何をテストしているのかを理解することがどのくらい難しいのか?
    • テストケースのサイズが小さいほど読みやすくなる
  • テストを実施することがどのくらい難しいのか?
    • 依存関係が少ないほど、テスト実施が簡単になる
GitHubで編集を提案

Discussion