最近のユニットテストなんかでは、JUnitのような、流しのツールを使うことが多いと思います(もしくは、画面からの流しでテストする)。
昔の単体テストのホワイトボックステストのような、ソースを1行1行止めて、確認するテストなんてのは、しないと。。
結果、「Junitなどを使ったユニットテスト < 昔の単体テスト」となることがある。
じゃあ、単体テスト - Junitなどを使ったユニットテスト = 何?っていう話をしてない気がするので、そのケースについて。
このケースには、いろいろあるけど、
1.モジュール内に、副作用があるが、その副作用について、どこにも記述されていないケース。
これは、ユニットテストだと、ケースすらあがらない場合があります。
正常系の場合、その副作用となるものを削除してしまうケースで、仕様書上には記載されていないが、プログラマの判断で利用したものが、それにあたります。
(ワークファイルや、ワーク用の共通メモリ領域(セッションを含む)など)
2.モジュール中、ある状況にならないとおきないケースで、そのケースは、ソースを追っかけて、止めない限り、テストが難しいケース。
ユニットテストでも、テストケースとして、本来は、あげなければいけませんが、あげてない場合がよくありますね(できないから)。
なんていうのがある。今回話題にするのは、2のケース。
2のケースで、格好の材料が最近出たので、これで説明しよう。
東証(富士通の障害?)のケース。
問題は、
<<テストケース>>
1.買い注文と、売り注文があり、
売り注文が1個残っている(部分約定)ときで、
買い注文が複数ある最中において、
2.この瞬間に、売り注文のキャンセルを入れる。
<<予想される結果>>
・買い注文の残りよりも先に売り注文をキャンセルし、
部分約定で終了すること
なにが、難しいって、1の状況を作っている最中に、2の注文を入れること
この1って、瞬時なのよ(1秒も、ないこともある)
これは、単体のホワイトボックステストか、あることを行って(なにをするのかは、後述する)、処理をとめない限り難しい。
コンピューターの処理は、
1.買い注文のキューと、売り注文のキューがあって、
2.そのキューを見ながら、条件判定をして、売買してよければ、
どちらかのキューがなくなるまで、「約定処理をループして実行する」
という感じだと思う。
これが約定モジュールとして、1モジュールになって、ユニットとしてテストしなければいけないというような、ケースがある。
(今回の富士通の件が、こうなってるかどうかはわかんないけど、こういう、「ループ処理最中に、あるデータを挿入して、そのループをとめる」というテストをしないといけないことは、人によっては、結構ある)。
こういうテストの場合、「ループ処理中に、データを滑り込んで打つ」って、最近のパソコンだと、きついのよ。
「いっせーのせ」で同時にやっても、もう、ループが終わってしまうんです。
100万件も投入しても。
かつ、1000万件とか、ありえない件数は、エラーになって、投入できなかったりする(>_<!)
ちょっと前にやると、ループに入る前に、データがはいってしまう。。。
なんつーので、ループ中に、何かするものの確認っていうのは、難しかったりする。
DBのデッドロックの確認なんかも、難しかったりする。
こういう場合、どうするのか。。。
ホワイトボックステストのように、1行1行とめられるなら、そのタイミングでいれればいいから楽なんだけど、1行1行、とめると、今度は、他の部分で、テストが大変だよね!
そういうときは、デバッグログを使うと楽かもよ。
デバッグログって、debug(書き出すメッセージ)のような、かんじじゃないですか?
ここで、引数の、書き出すメッセージが、ある言葉だったら、キー入力を待て(getchar()とか)みたいな、待たせる関数を実行するように、プログラムを記述する
(もしくは、あらかじめ、このときにやるべき処理を書いておく)。
そーすると、このテストのときだけ、このメッセージのところで、入力まちになる。
で、このデバッグ関数のほうを、このテストだけ、こっちを使うようにリンクする。
(javaなら、クラスファイルのパスを、こっちのほうをさきにすると、こっちをみる)
あとは、さっきの例なら、
1.買い注文と、売り注文があり、
売り注文が1個残っている(部分約定)ときで、
買い注文が複数ある
この瞬間のときに、
上記の(入力まちになる)メッセージで、デバッグログの関数を呼び出すように書いておけばいい。
ってこと。
なんてことは、結構あるのよねー。
ケータイなんかだと、この瞬間に、こういうことをすると。。。とか
なんか、パチンコの梁山泊のノリになってきたので、この辺で。