GNU Make を単体テストのテストランナーに使用しようとして困ったことあれこれ

make test で単体テストが実行されるようになっているプロジェクトを CI/CD に対応させる際に色々と右往左往してしまったので make マスターの面々からするとヤレヤレな内容かもしれませんが… メモがてら.

ビルドシステムに make が採用されている場合、多くの場合サブディレクトリ毎に makefile が用意されていて、それをプロジェクトのトップディレクトリに置かれた makefile から再帰 make するというのがよく行われると思います.  例えば以下のような構成のプロジェクトでは (a) から (b), (c) の makefile を再帰 make すると言った具合です.

├── Makefile          — (a)
├── subdir0
│      └── Makefile  — (b)
└── subdir1
│      └── Makefile  — (c)

また、(b) (c) の makefile には疑似 ターゲットとして test が定義されており、各々のディレクトリで make test を打つことで lib の生成や単体テストのビルドと実行が行われるようになっています.  このプロジェクトを CI/CD 対応しようとしたとき、ツール側から沢山あるサブディレクトリを一つ一つ個別に叩いて行くのは面倒なので当然 (a) に定義された test ターゲットを叩いて済ませたくなる訳ですが、単体テストの実行には一般的に以下の要求事項があり、この要求を満足する形でテストランナーを実装しなくてはなりません.

(1) 途中で fail しても後続のテストは実行したい.
(2) 全てのテストを実行し終えた後に一つでも fail していた場合に全体の終了ステータスをエラーにしたい.

さてどうしたものかと言うことで、真っ先に思いついたのが for でサブディレクトリを回す方法ですが、この方法では呼び出し元の make にエラーが帰らないため、(2) の条件を満たす事ができません.

次に思いついたのが、以下のように test ターゲットのコマンド行に再帰 make を直書きして -k (–keep-going)オプションで make を起動するという方法でしたが、-k オプションはターゲットのコマンド行で発生したエラーを無視して続行するのではなく、エラーを起こしたターゲットの構築を中断して、別のターゲットの構築を続けて実行するというオプションのようなので期待した動作をしません.  (というのをやってみて気づいた)

Normally make gives up immediately in this circumstance, returning a nonzero status. However, if the ‘-k’ or ‘–keep-going’ flag is specified, make continues to consider the other prerequisites of the pending targets, remaking them if necessary, before it gives up and returns nonzero status. For example, after an error in compiling one object file, ‘make -k’ will continue compiling other object files even though it already knows that linking them will be impossible.

https://www.gnu.org/software/make/manual/html_node/Errors.html

そうこうして最終的に「サブディレクトリ毎に test_subdir0, test_subdir1 のようなテスト専用ターゲットを (a) に用意して -k オプションを付けて叩くしかない」という結論に至ったのですが、実際はディレクトリの数も多く、ベタ書きはダサいなー嫌だなーと言うことで無い知恵絞ってヒネリだしたのが以下

なんかとりとめもなくなってしまった&もっといい方法がありそうな気がしてならなですが、とりあえず要件は満たせた!??

広告

コメントを残す

以下に詳細を記入するか、アイコンをクリックしてログインしてください。

WordPress.com ロゴ

WordPress.com アカウントを使ってコメントしています。 ログアウト /  変更 )

Google+ フォト

Google+ アカウントを使ってコメントしています。 ログアウト /  変更 )

Twitter 画像

Twitter アカウントを使ってコメントしています。 ログアウト /  変更 )

Facebook の写真

Facebook アカウントを使ってコメントしています。 ログアウト /  変更 )

%s と連携中