13

別のスレッドでテストを起動できる CppUnit のバージョンを教えてもらえますか?

私たちのテストの多くは非常に CPU 負荷が高いため (ただし、マルチスレッドではなく、もちろん、互いに独立しています)、今日のマルチコアでテストをはるかに高速に実行できるようになるという考えです。マシン。現在、すべてのテストを実行するには約 5 分かかります。これを1〜2分に短縮できれば素晴らしいことです...

4

2 に答える 2

6

テストが完了するのを待つのに5分は長い時間だと思います!数時間お試しください。次のようなモチベーションがありました。

Boostスレッドを使用すると、CppUnitスレッドは非常に簡単です。CppUnitにはすでに同期用のフックがいくつかあるので、次のようにしてスレッドセーフにする必要があります。

class Mutex : public CPPUNIT_NS::SynchronizedObject::SynchronizationObject
{
public:
    void lock() { this->mutex->lock(); }
    void unlock() { this->mutex->unlock(); }
private:
    boost::mutex mutex; 
};

これにより、テストランナーを変更して、TestResultスレッドを安全にすることができます。のようなものを書いてCPPUNIT_NS::TestResult testResult(new Mutex);ください。これがスレッド化されたテストスイートです。

class TestSuiteThreaded : public CPPUNIT_NS::TestSuite
{
public:
    TestSuiteThreaded(std::string name = "", int nThreads = 0)
        : TestSuite(name)
        , nThreads(nThreads ? nThreads : boost::thread::hardware_concurrency())
    {
    }
    void doRunChildTests(CPPUNIT_NS::TestResult *controller)
    {
        ThreadPool pool(this->nThreads);
        for (int i=0; i < getChildTestCount(); ++i)
        {
            pool.add(
                boost::bind(threadFunction, getChildTestAt(i)
                , controller));
        }
    }
private:
    static void threadFunction(
        CPPUNIT_NS::Test *test, 
        CPPUNIT_NS::TestResult *controller)
    {
        test->run(controller);
    }
    const int nThreads;
};

スレッド化されたテストスイートを簡単に使用するには、マクロが必要になる場合があります。TestSuiteThreadedスイートは、トップレベルのスイートとして、または同じテキストフィクスチャの複数のメソッドを含むスイートとして使用できる必要があります。後者の方法は次のとおりです。の代わりにこれを配置してCPPUNIT_TEST_SUITE_ENDください。この一部はCppUnitから貼り付けられているため、ライセンスを尊重してください。

#define CPPUNIT_TEST_SUITE_END_THREADED(n)                                     \
    }                                                                          \
    static CPPUNIT_NS::TestSuite *suite()                                      \
    {                                                                          \
      const CPPUNIT_NS::TestNamer &namer = getTestNamer__();                   \
      std::auto_ptr<CPPUNIT_NS::TestSuite> suite(                              \
         new CPPUNIT_NS::TestSuiteThreaded( namer.getFixtureName(), n));       \
      CPPUNIT_NS::ConcretTestFixtureFactory<TestFixtureType> factory;          \
      CPPUNIT_NS::TestSuiteBuilderContextBase context( *suite.get(),           \
                               namer,                                          \
                               factory );                                      \
      TestFixtureType::addTestsToSuite( context );                             \
      return suite.release();                                                  \
    }                                                                          \
  private: /* dummy typedef so that the macro can still end with ';'*/         \
    typedef int CppUnitDummyTypedefForSemiColonEnding__

今、の小さな問題がありThreadPoolます。公開されているものをいろいろ使ってみましたが、うまくいきませんでした。私の会社には1つありますが、ここで公開することはできません。だからあなた自身を転がしてください-スレッドプールはBoostの助けを借りて作るのがとても簡単で楽しいです。これが期待されるインターフェースですTestSuiteThreaded

class ThreadPool
{
public:
    // Create thread pool, launching n worker threads
    ThreadPool(unsigned n); 

    // Join all worker threads and clean up
    ~ThreadPool();

    // You can have add() do one of two things.  Both will work:
    // Either: push a new task to the back of the threadpool's work queue
    // Or: block until a worker is free then assign task to that thread
    void add(boost::function0<void> task);
};

これは読者の練習問題として残しておきます。楽しむ!

于 2011-04-06T10:22:03.700 に答える
3

この質問に対して得た回答の数を考えると、特に賛成票の数と比較して、アイデアがどれほど優れていても、優れたマルチスレッド ユニット テスト フレームワークを作成した人はいないと思います。これは、誰かが途方もなく有用なものを開発して名を馳せる絶好の機会のように見えます。

于 2011-03-08T21:02:28.473 に答える