jenkins + prove で失敗したテストを並列しないで再テストする試み

深淵な理由で(特に並列度をあげると)たまに落ちてしまうテストがあって、その度にあぁこれはたまに落ちちゃうやつなんですよねみたいな会話するのもいかがかと思っていた。

なので、落ちたテストがあった場合に並列しないで再度 prove してあげてそれでも落ちたらレポートするがいいかなぁと思ったのでこういう感じでやってみた。

JUNIT_NAME_MANGLE=none JUNIT_OUTPUT_FILE=output.xml prove -lvr -j5 --harness TAP::Harness::JUnit t

JUNIT_OUTPUT_FILE は TAP::Harness::JUnit が生成する xml を指定する環境変数

JUNIT_NAME_MANGLE に関しては TAP::Harness::JUnit - search.cpan.org に説明がある。

デフォルトだと hudson という値になるらしくこれは特殊な文字が _ に置換される。 perl の場合は ._ に, /. に置換される。 none の場合は特にされない。

hudson の場合だとこの値が t/hoge/foo.t の場合 t_hoge_foo_t, perl の場合 t.hoge.foo_t のようになる。ファイル名に _ が入ってくると生成された値からファイル名を推測するのがめんどくさい。

思いつきなので長く試したわけではないが none で jenkins を実行した際に多きな問題には出くわしてないので none でもよいのであれば生成された値から推測する必用がなくなる。(使っている jenkins 上だと / がよしなに _ に置換されているような気もする。)

この値は TAP::Harness::JUnit が生成する下記のような xml の中で使われる。

<?xml version='1.0' encoding='utf-8'?>
<testsuites>
  <testsuite name="t/foo/bar.t" errors="0" failures="0" tests="2" time="....">
    <system-out>
......
</system-out>
    <testcase classname="t/foo/bar.t" name="yap" time="...." />
    <testcase classname="t/foo/bar.t" name="tap" time="...." />
  </testsuite>
</testsuites>

なので失敗されたテストファイルを探すには errors, failures どちらかが 0 以上のものを探せば良さそう。errors, failures がどう定義されてるかは TAP::Harness::JUnitソースコードにある。

そんな感じで失敗したテストを今度は

JUNIT_NAME_MANGLE=none JUNIT_OUTPUT_FILE=rebuild_output.xml prove -lvr -j1 --harness TAP::Harness::JUnit t

のように実行し xml を merge し junit_output.xml のような jenkins が期待する名前で保存すると良さそう。