2026-09-21
TautologyTest.hs
module Main where
double :: Int -> Int
double x = x + 1
testDouble :: Bool
testDouble = double 5 == double 5
main :: IO ()
main = putStrLn (if testDouble then "pass" else "fail")
doubleは明らかに2倍になっていませんが、testDoubleはpassを報告します。何が問題で、どう直せばよいでしょうか?
Answer
testDoubleはdouble 5をdouble 5自身と比較しています。これはdoubleの実装が何であっても(正しくても、間違っていても)常にTrueになる、何も検証していない比較です。単体テストが検証すべきなのは、テスト対象の出力を、テスト対象とは独立に分かっている期待値と比較することです。期待値をテスト対象の呼び出し結果自身から作ってしまうと、テストはどんな実装に対しても素通りしてしまいます。ここでは期待値を独立した具体的な数値(10)に変えるだけで直ります:
testDouble :: Bool
testDouble = double 5 == 10
この最小限の修正だけでdouble自体は直っていませんが、testDoubleは正しくfailを報告するようになり、初めてdoubleが壊れていることが明らかになります。テストの役目は不具合を隠さず検知することであり、この修正によってようやくそれが果たされます。