皆さん、単体テストしてますか?
今回は、すこし稀な話題かもしれませんが、無限ループの単体テストについて取り上げてみたいと思います。
皆様のご存じのとおり、無限ループのある関数に対して単体テストをうまく実施することはできません。 テスト対象の関数が終了し、実行後の状態を確認しないと単体テストは完了とならないからです。
今回の記事では、C++testを使って無限ループの単体テストを行う方法をご紹介します。
関数単位で実行される単体テストは、
- 事前状態の設定
- 関数の実行
- 事後状態を確認
というような構成をとります(このような構成は、ホーアトリプルと呼ばれます)。
関数の実行による状態の変化、つまり事後状態を確認することで単体テストは完了します。
そのため、関数内の処理が無限ループに入ってしまうと、事後状態を確認することができず、単体テストは成立しないのです。
そのまま実行してもタイムアウトしてしまう・・・ |
C++testでは無限ループなどでテスト対象の処理が終わらない場合、タイムアウトでテスト失敗とみなします。(そのほかのツールではテストの実行がハングアップしてしまうかもしれません。)
そのため、無限ループするソースコードについては、レビューをしっかり行い単体テストは省略するという選択肢をとる場合もあります。
しかし、実際の開発現場では、ループ内の処理を確認したい、コードカバレッジを計測したい というケースがあるでしょう。
そうなると、どうにかして無限ループの単体テストを実施しなければなりません。
では、無限ループのある関数をテストするにはどうしたらよいのでしょう?
よく見かけるのは、
- #ifdefで一時的にループを排除する
- ループを抜けるための変数を用意する(デバッガで変数を書き換える)
すでに皆様の中にもこのような方法をとっている方がいるかもしれません。もちろん、それでテストが実施できていれば問題はありません。
ただ、1番目はソースコードが煩雑になりますし、2番目については、テストを自動化することができません。
そこで、登場するのが、
3. 「無限ループ用のC++test マクロを使う」
です。
無限ループの単体テストに対応するためのマクロ - C++test ユーザーズガイドより
名前
|
説明
|
CPPTEST_REGISTER_JMP(expression)
|
setjmp または sigsetjmp を使って内部的なジャンプ バッファーを設定し、渡される式を評価します。 CPPTEST_JMP API の呼び出しを使ってバッファーにジャンプすることができます。通常このマクロはテスト ケースの内部で使用され、テスト対象関数への呼び出しをラップします
|
CPPTEST_JMP (value)
|
longjmp の呼び出しを実行します (longjmp または siglongjmp 使用されます)。実行ステータスを最新の CPPTEST_REGISTER_JMP の呼び出しに戻します。通常このマクロはスタブの中で使用され、整数の引数を受け取ります。この引数は cpptestGetJmpReturn 関数によってテスト ケース内で返却されます。引数を使って、実行されるジャンプの正しさを検証できます 。
|
int CDECL_CALL cpptestGetJmpReturn();
|
最新の CPPTEST_JMP の呼び出しの戻り値、つまり longjmp/siglongjmp の引数を返します。これは setmp/sigsetjmp からの戻り値です。
|
これらのマクロを使うと、テスト対象のソースコードに手を加えることなく、無限ループの単体テストを実施することができます。
無限ループ用のC++testのマクロの利用イメージ |
テストケースの実装例 |
今回は、無限ループに関する、C++testの便利な使用方法をご紹介しました。
ご紹介したマクロについては、サンプルコードがC++testのマニュアルに記載されておりますので、あわせてご活用ください。
また、ユーザ様向けに、FAQサイトの公開もおこなっております。そちらもぜひご利用ください。
テクマトリックスではツールのご提供のみにとどまらず、導入前の支援から、導入開始時における開発者向けのトレーニング、CI(継続的インテグレーション)環境構築など、運用に乗せるための様々なサービスも実施しています。
ご興味のある方は、お気軽にお問い合わせください。
ご興味のある方は、お気軽にお問い合わせください。