5

標準の CMake コマンドの便利なラッパーをいくつか作成しました。この CMake スクリプト コードを単体テストして、その機能を確認したいと考えています。

私はある程度の進歩を遂げましたが、助けてもらいたいことが2つあります。

  1. 独自の CMake スクリプト コードを単体テストする「公式の」方法はありますか? CMake を実行するための特別なモードのようなものはありますか? 私の目標は「ホワイト ボックス テスト」です (可能な限り)。
  2. グローバル変数と変数スコープの問題を処理するにはどうすればよいですか? プロジェクトのキャッシュをロードしてグローバル変数をテストに挿入するか、テスト CMake ファイルを構成するか、-D コマンド ライン オプションを介してプッシュしますか? 変数スコープのシミュレーション/テスト (キャッシュされているものとキャッシュされていないもの、マクロ/関数/インクルード、参照によって渡されるパラメーター)?

まず、/Tests の下、特に Tests/CMakeTests の下にある CMake ソース コード (私は CMake バージョン 2.8.10 を使用しています) を調べました。膨大な数の種類があり、それらの多くは 1 つのテスト ケースに特化しているようです。

そのため、 CMake++などの利用可能な CMake スクリプト ライブラリも調べて解決策を確認しましたが、単体テストがある場合は、独自のライブラリ関数に大きく依存しています。

4

2 に答える 2

0

グローバル変数と変数スコープの問題を処理するにはどうすればよいですか? プロジェクトのキャッシュをロードしてテストにグローバル変数を挿入するか、テスト CMake ファイルを構成するか、-D コマンド ライン オプションを介してプッシュしますか?

一般的に言えば、現在存在するすべての方法 (キャッシュ経由、環境変数経由、および -D コマンドライン経由) は、予測できない動作を伴うため、いずれかのケースで悪い選択です。

これは私が思い出すことができる問題の最小のリストです:

  • どの変数が別の変数と交差/重複する可能性があり、いつですか?
  • 変数のロードまたは設定は、cmake 検出ステージ以外 (たとえば、cmake スクリプト モード) では適用できません。
  • 同じ一意の変数が、異なる OS/コンパイラ/構成/アーキテクチャなどに対して異なる値を保持することはできません。
  • Find*や などのシステム関数で表されるパッケージ (スコープではない) 用語に変数を添付することはできませんadd_subdirectory

私は長い間 cmake リスト内で変数を使用してきましたが、独自のソリューションを作成して、それらを cmake リストから一度に切り離すことにしました。

cmake スクリプトを介してスタンドアロン パーサーを作成し、ファイルまたはファイル セットから変数をロードし、一連のルールを定義して、事前定義された順序または厳密な順序で変数セットを有効にし、衝突と重複をチェックするという考え方です。

ここにいくつかの機能のリストがあります:

  • bool A=ONbool A=TRUEに等しいbool A=1
  • path B="c:\abc"Windows では (デフォルトの文字列の代わりにpath B="C:\ABC"明示的な変数) に等しいpath
  • B_ROOT="c:\abc"B_ROOT="C:\ABC"Windows では(変数名の末尾による変数の型検出)と等しい
  • LIB1:WIN="c:\lib1"Windows でLIB1:UNIX="/lib/lib1"のみ設定され、Unix でのみ設定されます (変数の特殊化)。
  • LIB1:WIN=c:\lib1, LIB1:WIN:MSVC:RELEASE=$/{LIB1}\msvc_release- 展開と特殊化によって変数を再利用する

ここですべてを説明することはできませんが、tacklelibライブラリ ( https://sourceforge.net/p/tacklelib/tacklelib/HEAD/tree/trunk/ ) を例として、実装を独自に調査することができます。

記述された設定ファイルの例はここに保存されています: https://sourceforge.net/p/tacklelib/tacklelib/HEAD/tree/trunk/_config/

実装: https://sourceforge.net/p/tacklelib/tacklelib/HEAD/tree/trunk/cmake/tacklelib/SetVarsFromFiles.cmake

必須として、configure_environment(...)マクロを使用して cmake リストを初期化する必要があります: https://sourceforge.net/p/tacklelib/tacklelib/HEAD/tree/trunk/CMakeLists.txt

tacklelibプロジェクト の詳細については、readme ファイルをお読みください: https://sourceforge.net/p/tacklelib/tacklelib/HEAD/tree/trunk/README_EN.txt

現在、プロジェクト全体は実験的なものです。

PS : cmake でパーサー スクリプトを作成するのは大変な作業です。最初に少なくとも次の問題を読んでください。

独自の CMake スクリプト コードを単体テストする「公式」の方法はありますか? CMake を実行するための特別なモードのようなものはありますか? 私の目標は「ホワイト ボックス テスト」です (可能な限り)。

私は独自の「ホワイトボックス」または独自のスクリプトをテストする方法を作成しました。別のcmakeプロセスでテストを実行するために、一連のモジュール(それ自体がライブラリに依存)を作成しました: https://sourceforge.net/p/tacklelib/tacklelib/HEAD/tree/trunk/cmake/tacklelib/testlib/

それに基づいて構築された私のテスト: https://sourceforge.net/p/tacklelib/tacklelib/HEAD/tree/trunk/cmake_tests/

アイデアは、テストを含むディレクトリとファイルの階層をテストディレクトリに配置することです。ランナーコードは、事前定義された順序でテストを検索し、個別の cmake プロセスで各テストを実行します。

function(tkl_testlib_enter_dir test_dir)
  # Algorithm:
  #   1. Iterate not recursively over all `*.include.cmake` files and
  #      call to `tkl_testlib_include` function on each file, then
  #      if at least one is iterated then
  #      exit the algorithm.
  #   2. Iterate non recursively over all subdirectories and
  #      call to the algorithm recursively on each subdirectory, then
  #      continue.
  #   3. Iterate not recursively over all `*.test.cmake` files and
  #      call to `tkl_testlib_test` function on each file, then
  #      exit the algorithm.
  #

、関数のセットは、ランナー cmake スクリプトまたは*.include.cmakeファイルの両方から使用できます。

TestLib.cmakeテスト モジュールを使用して外部 cmake プロセスを作成するサイクルを実行するように設計されている場所-*.test.cmakeこれらの関数は、ランナー スクリプトまたはインクルード モジュールから呼び出す必要があります (他のグループにはモジュールが含まれます -*.include.cmakeまたはテスト モジュール - *.test.cmake)。

tkl_testlib_enter_dir test_dir
tkl_testlib_include test_dir test_file_name
tkl_testlib_test test_dir test_file_name

テストコードを配置する必要があるすべてのモジュールにTestModule.cmake自動的に含まれる場所。*.test.cmake

その後tkl_test_assert_true、モジュール内で使用*.test.cmakeして、テストを成功または失敗としてマークします。

さらに、サブディレクトリのランナー スクリプトでフィルター パラメーターを使用して、_scriptsテストを除外することができます。

--path_match_filter <[+]regex_include_match_expression> | <-regex_exclude_match_expression>[;...]
--test_case_match_filter <[+]regex_include_match_expression> | <-regex_exclude_match_expression>[;...]

長所

  • TestModule.cmake、事前定義されたルールによるテストでディレクトリ全体をスキャンします。テストを順序付けるために正しい階層と名前付けを確認するだけで済みます。
  • ディレクトリごとに個別の包含ファイル*.include.cmakeを使用して、排他的包含、またはディレクトリとその子孫内のテストの順序を変更します。
  • *.test.cmakeファイルの存在は、デフォルトでテストを実行するための唯一の要件です。テストを排他的に含めたり除外したりするには、コマンド ライン フラグ--path_match_filter ...--test_case_match_filter ....

短所

  • ほとんどすべてのテスト関数は、functionキーワードを介して実装されています。これにより、いくつかの関数の機能が少し低下します。たとえば、tkl_test_assert_trueはテストが成功したか失敗したかのみをマークできます。tkl_return_if_failedテストを明示的に中断するには、マクロへの呼び出しを通じて分岐を行います。
  • テストを含むディレクトリ内のすべてのファイルには、接尾辞.test.cmake- テスト.include.cmake用、包含コマンド用 - が必要です。組み込みの検索ロジックはすべてこれに依存しています。
  • スクリプトを呼び出す独自のランナーを作成しましたRunTestLib.cmakerun allUNIX シェルの例は、https ://sourceforge.net/p/tacklelib/tacklelib/HEAD/tree/trunk/cmake_tests/_build/test_all.sh にあります。

現在、プロジェクト全体は実験的なものです。

于 2019-05-06T16:29:22.973 に答える