テストしやすいコード、しにくいコード

テストしやすいコード

参照透過性 を持った関数

引数のみで戻り値が決まる関数を、参照透過性のある関数という

  • 引数と戻り値が一対一対応するのでテストを準備するのは簡単
    • 後は、効率のいい網羅方法を考えればいい
  • Utility や Helper でもない限りまず無理だが・・・

状態が少なく再現しやすい関数、クラス

  • たかだか数個の変数を持った構造体を引数にとる関数
  • たかだか数個のグローバル変数に依存する関数
  • メンバー変数がたかだか数個のクラス
  • これらは、状態の再現が簡単に出来るのでテストしやすい

テストしにくいコード

プログラムの外に状態を持っている場合

  • 外部に接続されている機器だったり、現在時刻など、プログラムの中で自分が準備しているわけではないモノに依存しているコード
  • 外部にある状態とやり取りをする部分は、それ以外のもので直接再現できない
  • どうしてもモノが必要な部分を分離することなら出来る

プログラムの中に複雑な状態を持っているもの

  • 1 万個のグローバル変数を持っているとか
    • 『○は A, B, C に依存していて、×は A, C, D, E に依存していて、△は B, E, F に依存している』などの、状況のパターンが多い、もっと複雑な場合もある
  • グローバル変数は一つなんだけど、いろんな関数がそれを好き勝手に弄っているとか
    • 『今の状態は、A した後に B して C と D を同時にした後 E しなかった場合に発生する』などの、手順が複雑になる場合
  • これらの複雑な状態は、再現の手間がかかるためテストしにくい(面倒くさい)
    • ひどい場合だと、どうしてその状況になったのか分からない場合もある(この場合意図して再現することが出来ない)

今後の方針

  • 単体テストの出来ないもの、しにくいものと、出来るものを分離して、出来るもののテストを作っていく。
  • 出来ないものはちゃんと、実機や実際の動作で確認をして、それ以外のところはすべてテストで動作を担保していく。

用語メモ

副作用

  • 実行されると、結果を返す以外に何らかの状態変化を引き起こし、その関数自身もしくは他の関数の挙動や結果に変化を与えることを副作用と呼ぶ。
  • 関数にとっては受け取った引数から、戻り値を求め返すことが作用であり、それ以外は副作用。
  • IO 処理や、変数への代入がこれにあたる。

参照透過性

  • 入力が同じであれば、同じ戻り値を返し、同じ動作をする性質

参考資料