復帰後初めての不具合の原因調査は、JUnitを用いたテストについて。あるプロジェクトで、あるテストクラスが、ある環境で、うまく実行できないとのことだった。状況は、次の通り。
- PC上のEclipseからテストを起動すると、テストが実行され、テストの結果が見られる(テストがうまくいっているように見える)
- JenkinsからAntを呼び出してテストをすると、テストが実行されないように見える。コンソールの情報を見ても、テストターゲットが開始した情報までしか出力されていない
Eclipse上では動くのだから、このテストクラスと環境の相性が悪い?と、そんな雰囲気。でも、相性って何よ?
この時点では、「何かとてつもない、難解な原因が潜んでいるのでは?Jenkinsの不具合か?OSの不具合か?」と思ってしまう。悪い癖だ。結果、単純な設定ミスだったことが何回あったことか。
ま、まずは簡単なところから、手を動かして、調査対象をしぼっていこうかと。
- 他のテストクラス(数クラス)を指定して、JenkinsからAntを呼び出してテストをすると、どれもうまくいく
えっ?そうなの?「その(一番実行したい)テストクラス自体に問題がある可能性が高いなぁ」と思いながら。もう少し追い詰めていこうと、色々やってみる。
- Jenkinsが起動しているサーバで、直接antコマンドを実行すると、Jenkinsのコンソールと同じ情報が得られる
なので、Jenkinsは関係なさそう。やっぱり、テストクラス自体があやしい。
エラーになっているっぽいのに、正常終了?
しかし、何の情報も吐いてくれないと、取りつく島もない。ソースコードを見る前に、もう少し手を動かして、範囲を絞っていこう。
ってことは、やっぱりテストクラスの一部のロジックに問題がありそう。ちなみに、javaコマンドを直接たたいてJUnitを実行したのって、もしかしたら初めてかも。って感動している場合ではない。
ここで、「まさか。まさかこれ、このテストクラスで、強引にプログラムを終了させているのでは?」という不安がよぎった(以前にも似たようなことがあった)。ので、何をやっているか全く知らないテストクラスのソースコード(そこそこのボリューム)を、しぶしぶ読み進めていくと、、あった。
try { // 色々な処理 } catch (Exceprion e) { System.exit(0); }
エラー情報を握り潰し、正常な振りをして、Javaのプロセスそのものを落とす。凶悪だ。こんなコードは「ダメよ〜、ダメダメ」っていうか、もはや「ラッスン・ゴレライ」。
てか、最初からこのクラスが怪しかったんだから、嫌がらずに、ソースコードを見ておくべきだったでしょう。この調査能力の低さ、これも「ラッスン・ゴレライ」。
結局、この調査に何時間も費やしたが、何のことはない。
PCのEclipse上では、必要なリソースと環境が整っていたからテストが正常に進み、System#exitが実行されなかったから、不具合に気がつかなかったいうわけ。Jenkinsのサーバ上でテストをするには、環境が不十分で(おそらくDBまわりの設定)、エラーロジックに入り、System#exitが実行されていたというわけ。そもそも最初から、PC上とサーバ上では、全く違う動きをしていたのね。何が環境との相性だ。。
AntからJUnitを実行した場合は、これらが同じプロセス上で実行されるっぽいので、System#exitで、Antごと終了していたのだろう。
JUnitタスクのfork属性をonにしたときは、JUnitが、Antとは別プロセスで実行される。ただ、JUnitで用意されている終了の仕方ではなかったので、クラッシュした旨が表示されたのだろう。で、クラッシュ時にパイプをリフレッシュし、それまで保持していた情報を出力してくれたのだろう(情報は、ほとんどなかったけど)。
何にせよ、原因がわかってよかった。ほっとした。