2011-10-09 70 views
11

我有一套複雜的PHPUnit測試,其中一些涉及連接到世界各地的服務器,無論出於何種原因,有時會超時。PHPUnit - 自動重試失敗的測試X次?

當服務器超時時,我不想讓測試失敗,我想在實際標記爲失敗之前重試該測試一次或多次。

現在,我明白這可能不是處理我手邊情況的最佳方法。一個更好的解決方案是修復服務器。但是,這現在不在我的掌控之中。

因此,我真正喜歡的是告訴PHPUnit重新測試每個失敗的測試用例X次,並且只有在每次失敗時纔將其標記爲失敗。

任何想法?

編輯:你們中的很多人都回復了有用的建議,我不是做到這一點。我明白,謝謝。但是,我正在嘗試創建一個測試套件,用於測試包括遠程服務器在內的系統的運行情況。我理解用外部「模擬」響應測試代碼的某些部分的概念,但如果我的部分測試測試「完整堆棧」,我的夜晚也會睡得更好。

+2

根據你的編輯:1.當你說「它不是你的主人」時,你說「它不是你的系統的一部分」。因此,你不應該把它包含在你的測試中,因爲你無法影響它,它會僞造結果。 2.你永遠不會創建一個測試'$ this-> assertEquals(1,rand(0,1))',你會嗎?當你包含不確定的外部系統時,會發生這種情況。 – KingCrunch

回答

10

由於PHPUnit不支持這種開箱即用的行爲,您需要自己編寫循環代碼。與其在每個需要它的測試中都做它,請創建一個自定義測試用例基類(如果尚未),它將擴展PHPUnit_Framework_TestCase並提供該功能。

您可以得到看中,並覆蓋testBare()檢查註釋如@retry 5,循環,次數,通話parent::testBare(),吞除了最後的所有異常(或子集)。

public function runBare() { 
    // I'll leave this part to you. PHPUnit supplies methods for parsing annotations. 
    $retryCount = $this->getNumberOfRetries(); 
    for ($i = 0; $i < $retryCount; $i++) { 
     try { 
      parent::runBare(); 
      return; 
     } 
     catch (Exception $e) { 
      // last one thrown below 
     } 
    } 
    if ($e) { 
     throw $e; 
    } 
} 

或者你可以創建一個類似的輔助方法,它的重試次數和閉合/調用的參數和需要它的每一個測試調用它。

public function retryTest($count, $test) { 
    // just like above without checking the annotation 
    ... 
     $test(); 
    ... 
} 

public function testLogin() { 
    $this->retryTest(5, function() { 
     $service = new LoginService(); 
     ... 
    }); 
} 
+0

嗨大衛,你能提供更多詳細信息,如果失敗,我必須重試一次測試案例。 – Deep123

+0

@ Deep123哪部分不清楚? –

+0

感謝大衛的回覆。如果在沒有使用任何註釋的情況下發生故障,我只想重試我的測試用例。我做了什麼...... 我使用$ retryCount = 2將運行裸函數的代碼[在您的答案中定義]放在我的基類中,在此之後,我不清楚:( – Deep123

7

不完全是對您問題的回答,但我會說:無論如何,您的測試不應包含遠程資源(特別是當它們完全脫離您的手(與本地鏡像不同))。您應該將連接封裝到單獨的類中(例如Connection),並且在測試中,您可以模擬這些對象並使用靜態響應來處理遠程主機將返回的內容。

+1

這對於單元測試是正確的,但對於自動驗收測試,關於是否嘲笑外部服務仍然存在很多爭論。我們選擇不這樣做,它會增加測試的脆弱性。在這種情況下,重試可能會有所幫助。 –

1

我不認爲有這種支持,有人可以證明我錯了,但我會很驚訝,在這種情況下。

我認爲你可以做的不是在測試方法中立即聲明要被檢索的循環X次,並在成功時跳出循環,結果將被聲明。

這種簡單的方式,你已經想過了,但有一個缺點,就是爲每個測試方法添加更多的代碼。如果你有很多這樣做會增加維護負擔。否則,如果你想自動化更多,你可以實現一個PHPUnit_Framework_TestListener,保持關聯數組中失敗的測試計數,並與測試運行進行比較。不知道這條路線有多可行,但你可以試試。

0

您應該能夠創建一個數據庫連接斷言並在其他測試中實現該測試,例如「數據庫連接」。在該測試中,您可以嘗試多次,並在X嘗試後返回false。

3

與其連接到活動服務器,不應該使用模擬對象和固定裝置,以便來自別處的響應不會影響測試嗎?

您可以使用依賴注入來使用特定的HTTP客戶端,它將返回您告訴它的數據和響應代碼(取決於您的代碼寫入方式)。理想情況下,你的單元測試應該獨立於外部影響;你應該控制你正在測試的內容,例如,強制404或500錯誤應該是你測試的一個獨立部分。

與其試圖圍繞非確定性測試進行攻擊,不如考慮是否可以更改代碼以啓用模擬和測試裝置。

除此之外,您可能已經知道當然,恐怕我不知道告訴PHPUnit允許測試失敗的方法。這與工具應該做的事完全相反。

+0

+1,最後一個重要句子:「這與工具應該做的事情完全相反。」 – hakre