6

CppUnit を使用して一連の単体テストをセットアップしていますが、テストが実行されていないという問題があります。プロジェクトはいくつかの小さなライブラリに分割されており、単体テスト クラスを同じように分割し、それらすべてを 1 つのテスト プログラムにリンクすることを計画しました。問題は、テストクラスが独自のライブラリにあり、明示的に呼び出さない限り、メインのテストプログラムにリンクされないことです。つまり、

runner.addTest( TestClass::suite() );

テストクラスごとに個別に、TestFactoryRegistry の makeTests() メソッドを使用してテストのリストを取得することはできません。それらをすべてトップディレクトリにまとめてコンパイルすると、 makeTests() メソッドは正常に機能しますが、できればすべてのテストクラスを1つの場所に配置したくありません。

CppUnit documentation は、次の小さなヒントを提供します

ヘルパー マクロ使用時のリンクの問題?

プロジェクトを作成し、その単体テスト スイートを作成する場合、いわゆるヘルパー マクロ (CPPUNIT_TEST_SUITE_NAMED_REGISTRATION、CPPUNIT_REGISTRY_ADD、および CPPUNIT_REGISTRY_ADD_TO_DEFAULT) を使用することで作業が容易になります。問題は、これらのマクロを TestFixture クラス (たとえば MyTest など) のソース コード ファイルで使用し、次のような行を使用する場合です。

runner.addTest( CppUnit::TestFactoryRegistry::getRegistry().makeTest()

);

ファイル main.cpp の main() 関数では、テストはまったく実行されません。

その理由は、ビルド プロセスのステップの 1 つであるリンク ステージが、main.cpp に未定義のシンボルがない場合、最終的な実行可能ファイルにオブジェクト ファイル (.obj または .o ファイル) を挿入しないためです。

このように、AutoRegister 静的変数のインスタンス化を含むオブジェクト コードは、最終的な実行可能ファイルの一部ではなく、main() 関数で自分自身をランナーに挿入することができません。

mytest.o ファイルが main.o と統合されて最終的な実行可能ファイルになるように、main.cpp に未定義のシンボルを作成する必要があります。

ミシェル・ノラールが犯したトリック

しかし、これを機能させる方法については述べていません。私は自分でそれを理解したり、オンラインで例を見つけることができないほど十分に密集しています。

これで、ライブラリごとに個別の実行可能テストを作成することができ、最終的にはそのようになる可能性がありますが、最初にこれを機能させたいと思ったので、実行するテストプログラムを 1 つだけ使用してすべてをテストしました。これを機能させる方法のアイデア/例はありますか?

4

3 に答える 3

1

未定義のシンボルを main に追加することで、ランダムな外部シンボルを作成して、リンカーにテスト コードを含む外部ライブラリの検索を強制することを意味します。

たとえば、2 つのテスト ライブラリ fred と barney があると仮定すると、fredTestLib.cpp に次の行を追加するだけです。

int fredDummyInt = 0; // declare a unique symbol for the linker to resolve

barneyTestLib.cpp に、同様の行を追加します。

int barneyDummyInt = 0; // a different unique symbol for the linker to resolve

各ライブラリを異なる手順で個別にコンパイルできます。次に、メインのテスト プログラムで、リンカーに強制的にそれらを解決させます。したがって、これらの行を main.cpp に追加します。

extern int fredDummyInt;
extern int barneyDummyInt;
...
main () {
    ...
    fredDummyInt++; // give the linker some symbols to resolve
    barneyDummyInt++;
    ...

(上記のトリックの作成者が言っていることによると) 考え方は、リンカがすでに fredTest.lib で fredDummyInt を検索しているため、自動的に登録されたテストも見つけて解決するということです。

注:これが機能するかどうかを確認するためにこれを試していません!外見についての質問に答えているだけです。

考慮すべきもう 1 つの方法は、DLL でテストを作成し、LoadLibrary() を使用してそれらを明示的に実行することです。やり過ぎですが、MfcUi::TestRunner を使用する場合、おそらく、ロードするライブラリを選択してロードし、そのライブラリで実行するテストを表示して実行できる、小さなドロップダウン GUI を構築できます。

于 2009-06-24T14:36:40.967 に答える
0

この問題の解決策は、以前の状態のようにかなり単純です(ただし、あまりエレガントではない場合があります)。外部ライブラリにあるTestFixtureごとに、メインモジュールに次の2行のコードを追加する必要があります

#include <CppUnitTestFixtureExample.h>
CppUnitTestFixtureExample Test1;

使用されていない未使用のダミー変数を作成し、リンカーにテストフィクスチャをリンクさせるだけです。これで、メインモジュールにあるテストランナーがテストを実行できるようになります。

于 2012-01-25T14:09:49.980 に答える
0

この投稿はかなり古いものであることに気付きましたが、これに出くわした他の人にとっては、コードに参照を持たずにこれに対処する1つの方法は、リンカーに静的ライブラリ全体をバイナリに含めるように指示 (強制) することです。gcc および ld の man ページから利用可能な詳細領域と、この投稿もカバーしています: How to force gcc to link unreferenced, static C++ objects from a library

ld のマニュアル ページによると、オプションを明示的にオフにすることを検討することが重要です (上記の例の 1 つにも示されています)。

于 2013-01-15T21:46:44.687 に答える