第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度では なかなか奇麗に書けないものである。
あそこの機能は、関数にしておいた方がよかったなと思って、
うまく言っているソースでも、手を加えることがある。
こういった行為をリファクタリングと呼ぶ。


このリファクタリングの段階で、仕様を満たさないソースに誤って書き換えてしまうことがある(今回の大げさな例みたいに)。
だからといって、リファクタリングを恐れていては、いいソースは生まれてこない。


そこで、テストだ!!


ちゃんと仕様通りであることを示せるテストを用意しておけば、リファクタリングは恐れることはない。
リファクタリング後もちゃんとテストに合格することで、仕様を満たしていることを示せるからだ。