6

私たちのプロジェクトでは、単体テストに QtTestLib を使用しています。その理由は、可能な限りプロジェクト全体ですでに Qt を使用しており、Qt は GUI アプリケーションであるため、GUI インターフェイスをテストする機能が必要だったからです。

私たちのプロジェクトは MSVC によってコンパイルされているため、ソリューションが乱雑になるため、テストごとに個別のプロジェクト ファイルを用意する必要はありませんでした。したがって、すべてのテストに対して単一のプロジェクトを作成しました。すべてのテストは CIS (継続的インテグレーション) で自動化する必要があるため、いくつかの XSLT 変換を使用して、XML 形式の出力ファイルを介して Hudson にテストをプラグインしようとしました。

しかし、テストの出力に問題があるようです。すべてのテストに単一の main() を使用し、コマンドライン引数を各テストに送信するだけの場合:

#include "MyFirstTest.h"
#include "MySecondTest.h"

int main(int argc, char **argv)
{
  int result = 0;
  MyFirstTest test1;
  result |= QTest::qExec(&test1, argc, argv);
  MySecondTest test2;
  result |= QTest::qExec(&test2, argc, argv);
  return result;
}

その後、複数回書き換えられた結果ファイルが得られます。したがって、出力ファイル (xml など) を使用して多少自動化したい場合は、最後の結果のみが得られます。他のすべては上書きされます。

そのアプローチはすでに試しましたが、Hudson のような継続的インテグレーション システムを使用することはできません。だから私の質問は: 1 つの出力ファイルに結果を追加する機会はありますか? もちろん、パラメータを変更して QTest::qExec() で各テストを実行し、結果を別々のファイルに書き込むなどのいくつかの回避策を使用できますが、最善の方法ではないようです。理想的には、CIS で使用する単一の結果ファイルが必要です。

4

4 に答える 4

3

このトリックを使用すると、個々のテストxmlレポートを一時バッファー/ファイルに収集できます。すべて単一のテストバイナリから。QProcessを使用して、1つのバイナリ内から個別のテスト出力を収集しましょう。テストは、変更された引数を使用して自分自身を呼び出します。最初に、サブテストを適切に利用する特別なコマンドライン引数を紹介します。これらはすべて、テスト実行可能ファイル内にあります。便宜上、QStringListを受け入れるオーバーロードされたqExec関数を使用します。そうすれば、「-subtest」引数をより簡単に挿入/削除できます。

// Source code of "Test"

int
main( int argc, char** argv )
{
  int result = 0;

  // The trick is to remove that argument before qExec can see it; As qExec could be
  // picky about an unknown argument, we have to filter the helper 
  // argument (below called -subtest) from argc/argc; 

  QStringList args;

  for( int i=0; i < argc; i++ )
  {
     args << argv[i];
  }

  // Only call tests when -subtest argument is given; that will usually
  // only happen through callSubtestAndStoreStdout

  // find and filter our -subtest argument

  size_t pos = args.indexOf( "-subtest" );

  QString subtestName;

  if( (-1 != pos) && (pos + 1 < args.length()) )
  {
    subtestName = args.at( pos+1 );

    // remove our special arg, as qExec likely confuses them with test methods

    args.removeAt( pos );
    args.removeAt( pos );

    if( subtestName == "test1" )
    {
      MyFirstTest test1;
      result |= QTest::qExec(&test1, args);
    }

    if( subtestName == "test2" )
    {
      MySecondTest test2;
      result |= QTest::qExec(&test2, args);
    }

    return result;
}

次に、スクリプト/コマンドライン呼び出しで:

./Test -subtest test1 -xml ... >test1.xml
./Test -subtest test2 -xml ... >test2.xml

そしてここにあなたがいます-私たちはテスト出力を分離する手段を持っています。これで、QProcessの機能を引き続き使用してstdoutを収集できます。これらの行をメインに追加するだけです。明示的なテストが要求されていない場合は、実行可能ファイルを再度呼び出すという考え方ですが、特別な引数を使用します。

bool
callSubtestAndStoreStdout(const String& subtestId, const String& fileNameTestXml, QStringList args)
{
   QProcess proc;

   args.pop_front();

   args.push_front( subtestId );
   args.push_front( "-subtest" );

   proc.setStandardOutputFile( fileNameTestXml );

   proc.start( "./Test", args );

   return proc.waitForFinished( 30000 ); // int msecs
}

int 
main( int argc, char** argv )
{
   .. copy code from main in box above..

   callSubtestAndStoreStdout("test1", "test1.xml", args);
   callSubtestAndStoreStdout("test2", "test2.xml", args);

   // ie. insert your code here to join the xml files to a single report

   return result;
}

次に、スクリプト/コマンドライン呼び出しで:

./Test -xml           # will generate test1.xml, test2.xml

実際、将来のQTestLibバージョンでこれが簡単になることを願っています。

于 2012-04-15T20:20:24.933 に答える
3

私はこの汚い回避策を使用しました(Jenkinsで動作します):

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);
    int result = 0;
    freopen("MyAppTests_Test1.xml", "w", stdout);
    result |= QTest::qExec(new Test1, argc, argv);
    freopen("MyAppTests_Test2.xml",  "w", stdout);
    result |= QTest::qExec(new Test2, argc, argv);
    return result;
}

次に、Jenkins にビルド アクション「シェルの実行」を追加しました: ./path_to_MyAppTests -xml

ビルド後のアクション「xUnit テスト結果レポートを発行する」(QTestlib) を追加しました。QTestlib パターン: MyAppTests*.xml

于 2014-03-21T09:12:36.990 に答える