😁

ユニットテストについて

に公開

ユニットテストを調べるきっかけ

職場で単体テストは仕様書を確認しながら分岐を網羅するように作っています。
そして手動でバッチ実行したりするテストしているのですが、製造の人たちは自動化しているという話を聞いたため職場に導入できないかなと考え調べてみました。

ユニットテストとは

  • 最小単位のテスト
    ・プログラムの一部分(関数・メソッド・クラスなど)を単独でテストする。
    ・他の部分に依存せず、単体で動作することが求められる。
  • 自動化が一般的
    ・手作業ではなく、テストフレームワーク(例:bats, JUnit, pytest, NUnit)を使用して自動化するのが基本。
  • 継続的な検証に活用
    ・開発の途中でコードを変更した際に、他の部分へ影響を与えていないか素早く確認できる。
    ・CI/CD(継続的インテグレーション/デリバリー)で頻繁に実行される。

ユニットテストのメリット

  • バグの早期発見
    → 小さな単位でテストするため、不具合の原因を特定しやすい。
  • リファクタリングが容易
    → 既存の動作が保証されているため、安心してコードを変更できる。
  • コードの品質向上
    → テストを書くことで、意図しない動作を防ぐことができる。

Bats(Bash Automated Testing System)

BatsはBash用のテストフレームワークです。
実際にやってみます

四則演算を行うスクリプト

math.sh は四則演算(加算・減算・乗算・除算)を行うBashスクリプトです。

#!/bin/bash

operation=$1
num1=$2
num2=$3

case "$operation" in
  add)
    echo "$((num1 + num2))"
    ;;
  sub)
    echo "$((num1 - num2))"
    ;;
  mul)
    echo "$((num1 * num2))"
    ;;
  div)
    if [ "$num2" -eq 0 ]; then
      echo "Error: Division by zero" >&2
      exit 1
    else
      echo "$((num1 / num2))"
    fi
    ;;
  *)
    echo "Error: Invalid operation" >&2
    exit 1
    ;;
esac

このスクリプトは、引数として演算の種類 (add, sub, mul, div) と 2 つの数値を受け取り、それに応じた計算を実行します。
不正な演算(例: mod)やゼロ除算を行うとエラーメッセージを出力し、終了ステータス 1 を返します。

テスト用ファイルmath.batsを作成する

#!/usr/bin/env bats

setup() {
  script="./math.sh"
}

@test "加算が正しく動作する (2 + 3 = 5)" {
  run $script add 2 3
  [ "$status" -eq 0 ]
  [ "$output" -eq 5 ]
}

@test "減算が正しく動作する (10 - 4 = 6)" {
  run $script sub 10 4
  [ "$status" -eq 0 ]
  [ "$output" -eq 6 ]
}

@test "乗算が正しく動作する (3 * 7 = 21)" {
  run $script mul 3 7
  [ "$status" -eq 0 ]
  [ "$output" -eq 21 ]
}

@test "除算が正しく動作する (8 / 2 = 4)" {
  run $script div 8 2
  [ "$status" -eq 0 ]
  [ "$output" -eq 4 ]
}

@test "ゼロ除算のエラー処理 (5 / 0)" {
  run $script div 5 0
  [ "$status" -eq 1 ]  # エラーコード 1 を期待
  [[ "$output" == *"Error: Division by zero"* ]]  # エラーメッセージを確認
}

@test "無効な演算を実行した場合のエラーハンドリング" {
  run $script mod 10 3
  [ "$status" -eq 1 ]  # エラーコード 1 を期待
  [[ "$output" == *"Error: Invalid operation"* ]]  # エラーメッセージを確認
}

テストのポイント

  • run $script add 2 3 のようにスクリプトを実行
  • status で終了ステータスをチェック(0 は成功、それ以外はエラー)
  • output で標準出力をチェック
  • エラーハンドリング(ゼロ除算や無効な演算)のテストも実施

statusとoutputとは

status(終了ステータス)

  • status は 実行したコマンドの終了ステータス(戻り値) を表す
  • 0 は成功、それ以外(1 以上)はエラーを意味する

output(標準出力)

  • output は 実行したコマンドの標準出力(stdout)の内容 を表す
  • 計算結果やエラーメッセージが格納される

テストの実行

以下のコマンドでテストを実行できます。

bats math.bats

テスト結果の例

成功例

 ✓ 加算が正しく動作する (2 + 3 = 5)
 ✓ 減算が正しく動作する (10 - 4 = 6)
 ✓ 乗算が正しく動作する (3 * 7 = 21)
 ✓ 除算が正しく動作する (8 / 2 = 4)
 ✓ ゼロ除算のエラー処理 (5 / 0)
 ✓ 無効な演算を実行した場合のエラーハンドリング

6 tests, 0 failures

すべてのテストが成功すると、このように 「0 failures」 となります。

失敗例

✗ ゼロ除算のエラー処理 (5 / 0)
   (from function `assert_output' in file math.bats, line 22)
     `[[ "$output" == *"Cannot divide by zero"* ]]' failed

6 tests, 1 failure

この場合、期待したエラーメッセージと実際の出力が一致していない ため、テストが失敗しています。
(エラーメッセージが "Error: Division by zero" であるべきところを "Cannot divide by zero" と誤って期待している可能性があります。)

テストまとめ

  • math.sh は四則演算を行う Bash スクリプト
  • math.bats を使い、自動化されたユニットテストを実行
  • bats math.bats でテストを実行し、結果を確認できる
  • エラー処理(ゼロ除算・無効な演算)もテストすることが重要

最後に

ユニットテストがあれば単体テストが自動化が出来て、手作業よりも効率的にバグが見つけられそうですね。
改修が入った時のデグレテストにも利用できそうです。
私の職場で利用されていないのは、以下の理由が考えられるかな。

  • 製造の人は最小単位でテストをしている
  • プロジェクトの予算と納期が厳しい
  • そもそも出来る人がいないから導入していない
    自動化のメリットよりも導入の手間や学習コストが高そうなので取り入れてないだけで、時間があるときに私がつくってしまおうかな。

Discussion