REPLと単体テスト
Pythonのことを考えていて、TDDの文脈での単体テストの意義にふと気がついた。つまり、失敗するテストを先に書いて、それを通るように実装をする、という方法論の意義に気がついた、ということだ。
PythonやHaskell、Lisp、ScalaのようなREPLがある言語で開発をするとき、僕はテストを先に書く理由が今まであまり腑に落ちていなかった。それはおそらく実装して、REPLでデータを渡せば動作確認できるからだ。
もちろんユニットテストを書いておいた方が再利用性とかを考えると良いだろうし、リファクタリングの助けになるのも分かる。ただ、コードを書き始める前にやるほどのこととは思えなくて、プログラムに対してユニットテストを書くことは、文章に対して推敲するような行為だと捉えていたのだ。コードがあっていそうなことはREPLで確認するのが手軽で、ユニットテストは重い作業というか。この重さは面倒なだけでなく、実際に開発速度を落としていたように感じる。
さらには何がほしいか明確ではない段階で単体テストを書いて、実装してみて、なんか違ったときにはたくさん変更する箇所があって、テストケースとプログラムの修正順序が逆転することもある(このプログラムは正しいので、怒っているテストを修正する、ということ)。
単体テスト as 推敲のパラダイムは割と悪くないと思っている。世間の皆さんはどう思っていて、実際的な方法はどんななんだろうか。
P.S. GoとかRustみたいな言語では単体テストは、もっとガンガン単体テストを書けば良いと思う。というのもこれらの言語にはREPLいから。単体テストを書けばmain関数に手を入れずに、比較的お手軽に小さい確認をできる。
ここまで書いて思ったのだけど、REPLで確認するレベルの動作確認をGoとかではテストで確認する必要はあるだろうか?(僕はないと思うことが多い) 型検査やlinterにかけることが気持ちとしては同等の検査? 言語が違えばプログラムの構造が質的に変わるので、細かい比較はあまり意味がないか。
結論は 「REPL ~ 静的検査」の対応がなんとなくあって、単体テストはもう少し大きめな検査? あまりスッキリしない。この辺りの考えを胸に置いて、コーディングしていれば知見が得られるかもしれない。