2011-09-15 71 views
1

相關代碼謂詞,這是來自UnitTest++/TestRunner.h單元測試++問題:試圖使用有狀態

class TestRunner 
{ 
public: 
    explicit TestRunner(TestReporter& reporter); 
    ~TestRunner(); 

    template <class Predicate> 
    int RunTestsIf(TestList const& list, char const* suiteName, 
        const Predicate& predicate, int maxTestTimeInMs) const 
    { 
     Test* curTest = list.GetHead(); 

     while (curTest != 0) 
     { 
      if (IsTestInSuite(curTest,suiteName) && predicate(curTest)) 
      { 
       RunTest(m_result, curTest, maxTestTimeInMs); 
      } 

      curTest = curTest->next; 
     } 

     return Finish(); 
    } 

private: 
    TestReporter* m_reporter; 
    TestResults* m_result; 
    Timer* m_timer; 

    int Finish() const; 
    bool IsTestInSuite(const Test* const curTest, char const* suiteName) const; 
    void RunTest(TestResults* const result, Test* const curTest, int const maxTestTimeInMs) const; 
}; 

這裏是我的判別式類我想修改,讓它做什麼,我想:

class ListFilterRemember { 
    char **list; 
    int n; 
    Test **testsAlreadyRun; 
    int index_tar; 
    int max_allocd; 
public: 
    ListFilterRemember(char **list_, int count) { 
       int testCount = 0; 
     Test* curTest = Test::GetTestList().GetHead(); 
     while (curTest != 0) { 
      testCount++; 
     } 
       list = list_; n = count; max_allocd = testCount; 
     testsAlreadyRun = new Test *[max_allocd]; 
     index_tar = 0; 
    } 
    bool operator()(const Test* const t) const { 
     for (int i=0;i<index_tar;++i) { 
      if (testsAlreadyRun[i] == t) { return false; } 
     } 
     for (int i=0;i<n;++i) { 
      std::string dot_cpp_appended = std::string(list[i]) + ".cpp"; 
      if (!strcasecmp(t->m_details.testName, list[i]) || 
        !strcasecmp(t->m_details.suiteName, list[i]) || 
        !strcasecmp(t->m_details.filename, list[i]) || 
        !strcasecmp(t->m_details.filename, dot_cpp_appended.c_str()) || (
          filename_dir_prefix_len < (int)strlen(t->m_details.filename) && (// ensure the ptr arith in next 2 lines doesn't go out of bounds 
            !strcasecmp(t->m_details.filename+filename_dir_prefix_len, list[i]) || 
            !strcasecmp(t->m_details.filename+filename_dir_prefix_len, dot_cpp_appended.c_str()) 
          ) 
        ) || (
          std::string::npos != findCaseInsensitive(t->m_details.testName,list[i]) 
        ) 
      ) { 
       // erring on the side of matching more tests 
       //printf(" running\n"); 
       if (index_tar >= max_allocd) throw std::runtime_error("Did not allocate! Segfault here."); 
       testsAlreadyRun[index_tar] = (Test *)t; 
       index_tar += 1; 
       return true; 
      } 
     } 
     //printf(" not running\n"); 
     return false; 
    } 
    ~ListFilterRemember() { 
     delete[] testsAlreadyRun; 
    } 
}; 

您會看到它在TestRunner.h中定義的方式附加了一個const限定符,這使得我的operator()函數無法更改成員變量。我需要進行這些更改,以便記住哪些測試已經運行,因此我不會再運行它們。可能會再次運行的風險是我打算多次運行RunTestsIf()

我在命令行中輸入測試列表,根據名稱指定要運行哪些測試。這就是所有字符串匹配代碼的用途。我仍然想使用這些,但是這次我想改進它,以便我指定的測試將按照我指定的順序運行。爲了做到這一點,我必須移動測試運行器,以便循環使用我的指定的測試列表並基於它們逐一進行匹配。

想法?我會在UnitTest ++代碼中加入const,但如果我不需要,我不想破壞它。

回答

1

您可以使用mutable關鍵字,但測試的結構方式表明測試運行器可能不會重複使用謂詞的相同實例,因此您的更改可能在測試之間丟失。當然,如果發佈的代碼是整個測試運行器,那麼它看起來每次都會調用相同的Predicate實例。

+0

我從來不知道'mutable'關鍵字。感謝您指出 - 這幾乎就像是爲這種情況量身定製的......我必須做一些測試,以查看引擎蓋下是否存在與Predicate有關的奇怪事件,但我會grepped src和我發佈的位是對「Predicate」的唯一引用。我也可能**可能**稍微編輯UnitTest ++的src來破解它的工作,但它很可能需要我重新編譯它。只是...不好。不管怎樣,謝謝。 –

0

通常你會希望單元測試有一組確定性的東西來測試。這可能更接近集成測試。這並不是必然的,只要確保先測試較小的位。

這就是說,UnitTest ++的設計很小,很容易修改。我會擴展或包裝它以滿足您的需求,但不會破壞現有的功能。

+0

運行我的單元測試可執行文件而沒有任何cmd行參數使得它以通常的方式運行所有測試。我只是想,嘿爲什麼不讓它做我想做的事情。 –