単体テスト
Mesonには、完全に機能する単体テストシステムが付属しています。これを使用するには、単に実行可能ファイルをビルドし、それをテストで使用します。
e = executable('prog', 'testprog.c')
test('name of test', e)
必要なだけテストを追加できます。これらはコマンドmeson test
で実行されます。
Mesonはすべてのテストの出力をキャプチャし、ログファイルmeson-logs/testlog.txt
に書き込みます。
テストパラメータ
一部のテストでは、コマンドライン引数または環境変数を使用する必要があります。これらは簡単に定義できます。
test('command line test', exe, args : ['first', 'second'])
test('envvar test', exe2, env : ['key1=value1', 'key2=value2'])
複数の値を配列として指定する必要があることに注意してください。
MALLOC_PERTURB_
デフォルトでは、環境変数MALLOC_PERTURB_
は1..255の間のランダムな値に設定されます。これは、非GCCコンパイラを含むglibcを使用する構成でメモリリークを見つけるのに役立ちます。この機能は、test()
で説明されているように無効にできます。
ASAN_OPTIONS、UBSAN_OPTIONS、およびMSAN_OPTIONS
デフォルトでは、環境変数ASAN_OPTIONS
、UBSAN_OPTIONS
、およびMSAN_OPTIONS
は、検出された違反時にアボートを有効にし、バックトレースを表示するように設定されています。この機能は、test()
で説明されているように無効にできます。
カバレッジ
Mesonにコマンドラインフラグ-Db_coverage=true
を与えることでカバレッジ測定を有効にすると、テスト実行後(呼び出される関数のリストを収集するにはテストを実行する必要があります)、カバレッジレポートを生成できます。Mesonは、インストールされているカバレッジジェネレーターツールを自動検出し、対応するターゲットを生成します。これらのターゲットは、Gcovr(バージョン3.3以上)によって提供されるcoverage-xml
とcoverage-text
、Gcovr(バージョン4.2以上)によって提供されるcoverage-sonarqube
、およびlcovとGenHTMLまたはGcovrが必要なcoverage-html
です。便宜上、可能であれば3種類のカバレッジレポートタイプをすべて生成する高レベルのcoverage
ターゲットも生成されます。
これらのコマンドの出力は、ビルドディレクトリのログディレクトリmeson-logs
に書き込まれます。
並列処理
テスト時間を短縮するために、Mesonはデフォルトで複数の単体テストを並行して実行します。ファイルやD-Bus名などの一部のリソースを独自に保持する必要があるため、並行して実行できないテストがあるのが一般的です。これらのテストは、キーワード引数で指定する必要があります。
test('unique test', t, is_parallel : false)
その後、Mesonは他の単体テストが同時に実行されていないことを確認します。並行ではないテストは実行に時間がかかるため、可能な限り、単体テストを並列実行可能にすることをお勧めします。
デフォルトでは、Mesonはテストマシン上のコア数と同じ数の同時プロセスを使用します。これは、次のように環境変数MESON_TESTTHREADS
でオーバーライドできます。
$ MESON_TESTTHREADS=5 meson test
MESON_TESTTHREADS
を0に設定するとデフォルトの動作(コア数)が有効になり、無効な値を設定するとジョブ数が1に設定されます。
優先度
(バージョン0.52.0で追加)
テストには、テストが開始されるタイミングを決定する優先度を割り当てることができます。優先度の高いテストは最初に開始され、優先度の低いテストは後で開始されます。デフォルトの優先度は0であり、Mesonは同じ優先度のテストの順序を保証しません。
test('started second', t, priority : 0)
test('started third', t, priority : -50)
test('started first', t, priority : 1000)
テストの優先度はテストの開始順序にのみ影響し、後続のテストは前のテストの完了にかかる時間に影響されることに注意してください。したがって、実行時間の短い優先度の低いテストが完了した場合でも、優先度の高いテストが実行されている可能性があります。
スキップされたテストとハードエラー
テストによっては、実行時にのみ実行できないことを判断できる場合があります。
デフォルトのexitcode
テストプロトコルの場合、この場合のGNU標準のアプローチは、エラーコード77でプログラムを終了することです。Mesonはこれを検出し、これらのテストを失敗ではなくスキップされたものとして報告します。この動作はバージョン0.37.0で追加されました。
TAPベースのテストの場合、スキップされたテストは、1..0 # SKIP
で始まる単一行を出力する必要があります。
さらに、テストがセットアップに失敗し、期待される失敗としてマークされていても失敗する可能性がある場合があります。この場合のGNU標準のアプローチは、エラーコード99でプログラムを終了することです。ここでも、Mesonはこれを検出し、should_fail
の設定を無視して、これらのテストをERROR
として報告します。この動作はバージョン0.50.0で追加されました。
テストツール
Mesonテストツールの目標は、さまざまな方法でテストを実行するための簡単な方法を提供することです。このツールは、ビルドディレクトリで実行するように設計されています。
最も簡単な方法は、すべてのテストを実行することです。
$ meson test
テストのサブセットの実行
わかりやすくするために、次を含むmeson.buildを検討してください
test('A', ..., suite: 'foo')
test('B', ..., suite: ['foo', 'bar'])
test('C', ..., suite: 'bar')
test('D', ..., suite: 'baz')
次のように名前でテストを指定します
$ meson test A D
特定の(サブ)プロジェクトからテストを実行できます
$ meson test (sub)project_name:
または、特定のプロジェクトの特定のテストを実行できます
$ meson test (sub)project_name:test_name
バージョン1.2.0以降、プロジェクト名とテスト名にワイルドカードを使用できます。たとえば、「foo」で始まるすべてのテストと、「bar」で始まるプロジェクトのすべてのテストを実行するには
$ meson test "foo*" "bar*:"
スイートsuite
に属するテストは、次のように実行できます
$ meson test --suite (sub)project_name:suite
バージョン0.46以降、最上位プロジェクトの場合、(sub)project_name
を省略できます。
複数のスイートは次のように指定されます
$ meson test --suite foo --suite bar
注:スイートと特定のテスト名の両方を指定する場合、テスト名はスイートに含まれている必要があります。ただし、これは冗長です。特定のテスト名またはスイートのいずれかを指定する方がより便利です。
その他のテストオプション
テストを複数回実行する必要がある場合があり、これは次のように行われます
$ meson test --repeat=10
Mesonは、テストの現在の反復回数をMESON_TEST_ITERATION
環境変数に設定します(1.5.0で追加)。
Valgrindなどのヘルパー実行可能ファイルを介してテストを呼び出すには、--wrap
引数を使用します
$ meson test --wrap=valgrind testname
ラッパーバイナリへの引数は、次のように指定できます
$ meson test --wrap='valgrind --tool=helgrind' testname
Mesonは、GDBでテストを実行することもサポートしています。これを行うだけです
$ meson test --gdb testname
Mesonはテストを実行するために設定されたgdb
を起動します。プログラムを開始するには、GDBコマンドプロンプトでrun
と入力します。
2番目のユースケースは、まれにのみセグメンテーションフォルトが発生するテストです。この場合、次のコマンドを呼び出すことができます
$ meson test --gdb --repeat=10000 testname
これにより、GDBでテストが最大10,000回自動的に実行されます。プログラムがクラッシュした場合、GDBは停止し、ユーザーはアプリケーションをデバッグできます。この場合、テストのタイムアウトは無効になっているため、開発者がデバッグしている間、meson test
はgdb
を強制終了しないことに注意してください。欠点は、テストバイナリがフリーズした場合、テストランナーが永久に待機することです。
GDBバイナリがPATH変数にない場合や、ユーザーがGDBの代替を使用したい場合があります。したがって、呼び出されたGDBプログラムは指定できます(0.52.0で追加)
$ meson test --gdb --gdb-path /path/to/gdb testname
$ meson test --print-errorlogs
--interactive
オプションを使用すると、テストを対話的に実行できます。meson test --interactive
は、stdout、stdin、およびstderrが呼び出し元のターミナルに直接接続された状態でテストを呼び出します。これは、テストが失敗した場合にデバッグシェルが生成されるコンテナまたは仮想マシンで実行される統合テストの場合に役立ちます(1.5.0で追加)
$ meson test --interactive testname
Mesonは、環境変数として、失敗したテストによって生成された出力と、その他の有用な情報を報告します。これは、たとえば、Travis-CI、Jenkinsなどでテストを実行する場合に役立ちます。
デフォルトでは、テストからの出力は最後の100行に制限されます。表示する最大行数は、--max-lines
オプションで設定できます(1.5.0で追加)
$ meson test --max-lines=1000 testname
タイムアウト
テストケースオプションでは、timeout
オプションは秒数で指定されます。
テストケースでタイムアウトを無効にするには、テストケースが完了するまで無限の時間を許可するように、timeout: 0
または負の値を追加します。
テストの実行では、タイムアウトをオーバーライドするためのコマンドライン引数も指定できます
$ meson test --timeout-multiplier 0
詳細については、meson test -h
を実行してMesonのコマンドラインヘルプを参照してください。
レガシーノート
meson test
が機能しない場合は、Mesonの古いバージョンを使用している可能性があります。その場合は、代わりにmesontest
を呼び出す必要があります。mesontest
も機能しない場合は、0.37.0より前の非常に古いバージョンを使用しているため、アップグレードする必要があります。
テスト出力
Mesonは、テスト実行の詳細な結果を含むいくつかの異なるファイルを書き込みます。これらは、$builddir/meson-logs/に書き込まれます。
testlog.json
これは適切なjsonファイルではありませんが、行ごとに1つの有効なjsonオブジェクトを含むファイルです。このファイルは、各テストの実行時に各行がストリーミング出力されるように設計されているため、テストハーネスの実行中にストリームとして読み取ることができます
testlog.junit.xml
これは、実行されたすべてのテストの有効なJUnit XML記述です。ストリーミング出力されず、すべてのテストの実行が完了した後に一度だけ書き込まれます。
テストでtap
プロトコルを使用する場合、各テストはテストスイートコンテナとして記録され、各ケースは結果の番号で名前が付けられます。
テストでgtest
プロトコルを使用する場合、Mesonは、独自のJUnit XMLを生成するためにテストに引数を挿入します。MesonはこのXMLファイルをそのXMLファイルの一部として含めます。
0.55.0の新機能
検索の結果は