第83回 テスト! Test!! テストぉおお!!! テストとはなにか!?
テストというものをご存知だろうか。ソフトウェアが正しく動いているかどうか確かめるものである。
ファイルに出力するプログラム
例えば、簡単なプログラムとして、
$ perl bingo.pl > hoge.txt
とすれば、hoge.txtに
aaa bbb ccc
と表示するプログラムを作りたいとしよう。
ソース:
use strict; print 'aaa', "\n"; print 'bbb', "\n"; print 'ccc', "\n";
こんなソースが書けるだろう。
実行:
$ perl bingo.pl > hoge.txt
確認:
$ cat hoge.txt aaa bbb ccc
このように、catで出力させると確かに望みのものが出力されているのがわかる。
このように、望みの結果を得れたので、
- ファイルに、値が正しく出力されている
というテスト項目は満たしたといえる。
diffコマンド
diffコマンドというものをご存知だろうか。
diffコマンドを用いれば、二つのファイルの内容にどのような違いがあるか教えてくれる。
この違いのことを「差分」と呼ぶ。
いま、ここに a.txt と b.txt を用意しよう。
a.txt
aaa bbb ccc
b.txt
aaa ddd ccc
この2つのファイルの違いは2行目である。
bbb と ddd
が違っているのである。この違い(差分)を教えてくれるのがdiffコマンドである。
$ diff a.txt b.txt 2c2 < bbb --- > ddd
このように差分を表示してくれるのである。
ちなみに、差分がない場合はなにも表示されない。
つまり、なにも表示されなければ違いはないということだ。
このdiffコマンドを使って、さきほどのソースをテストしよう。
$ perl bingo.pl > hoge.txt $ diff hoge.txt a.txt
OK、なにも表示されなかったので、hoge.txt と a.txtの内容は同じだ。
a.txt が、正しい出力結果なので、a.txtと同じ内容であるということが示せたのでテストは合格である。
改良を恐れるな!
さて、今回はあまりにも簡単な例だが、
このように何度やってもテストが合格するようにしておくのは大切な事だ。
さて、これで、diffコマンドでa.txtと差分がでなければ、合格であることがわかったので、bingo.plを少しいじってみることにしよう。
例えば、print文を3つも書くのなんてなんかダサイと思って次のようなソースにしたとしよう。
use strict; for('aaa', 'bbb', 'xxx'){ print $_, "\n"; }
ああ、そうだ。
これは、大げさな例だ。
重大なミスを盛り込んでしまったのだ。
'ccc' にすべきところを 'xxx'にしてしまったんだ。
さて、ソースに手を加えたわけだから、テストしないわけには、本当に正しいソースを書いたとは言えない。
さあ、テストしてみよう!!
$ perl bingo.pl > hoge.txt $ diff hoge.txt a.txt 3c3 < xxx --- > ccc
な、なんてことだ!!! diffコマンドで出力されてしまった!!!!
そう。つまり、ソースをいじったせいで、テストが合格しなかったのだ!!!!
しかし、テストを欠かさなかったおかげで、ミスを残したままにすることは防げたのである。
テストを通るようにソースを書き直そう。
use strict; for('aaa', 'bbb', 'ccc'){ print $_, "\n"; }
テスト:
$ perl bingo.pl > hoge.txt $ diff hoge.txt a.txt
もちろん、またソースをいじったので、テストをして合格することを確認するのだ。
ソースというのは、1度では なかなか奇麗に書けないものである。
あそこの機能は、関数にしておいた方がよかったなと思って、
うまく言っているソースでも、手を加えることがある。
こういった行為をリファクタリングと呼ぶ。
このリファクタリングの段階で、仕様を満たさないソースに誤って書き換えてしまうことがある(今回の大げさな例みたいに)。
だからといって、リファクタリングを恐れていては、いいソースは生まれてこない。
そこで、テストだ!!
ちゃんと仕様通りであることを示せるテストを用意しておけば、リファクタリングは恐れることはない。
リファクタリング後もちゃんとテストに合格することで、仕様を満たしていることを示せるからだ。