延遲處理 tearDown 的例外保護#
待辦清單:
Invoke test methodInvoke setUp firstInvoke tearDown afterward- Invoke tearDown even if the test method fails
- Run multiple tests
- Report collected results
Log string in WasRun
作者原本打算實作「即使 test method 拋出例外,tearDown() 仍然被呼叫」的功能。然而,要讓測試運作需要捕捉例外,如果在實作中犯了錯誤,例外就不會被回報,我們也看不到錯誤。
重點: 測試的實作順序很重要。選擇下一個要實作的測試時,應該找一個能教你一些東西且你有信心能讓它運作的測試。如果讓一個測試通過了但下一個卡住,可以考慮回退兩步。
引入 TestResult#
我們希望看到任意數量測試的執行結果,例如:"5 run, 2 failed, TestCaseTest.testFooBar - ZeroDivideException, MoneyTest.testNegation - AssertionError"。如果測試沒有被呼叫或結果沒有被回報,至少我們有機會發現錯誤。
讓 TestCase.run() 回傳一個 TestResult 物件來記錄執行結果:
def testResult(self):
test= WasRun("testMethod")
result= test.run()
assert("1 run, 0 failed" == result.summary())先用 Fake Implementation 開始:
class TestResult:
def summary(self):
return "1 run, 0 failed"讓 TestCase.run() 回傳 TestResult:
def run(self):
self.setUp()
method = getattr(self, self.name)
method()
self.tearDown()
return TestResult()逐步實體化#
測試通過後,開始將 summary() 的假實作逐步實體化(make real)。首先讓執行次數成為符號常數:
def __init__(self):
self.runCount= 1
def summary(self):
return "%d run, 0 failed" % self.runCountrunCount 不應是常數,而是透過計算得出。初始化為 0,每次執行測試時遞增:
def __init__(self):
self.runCount= 0
def testStarted(self):
self.runCount= self.runCount + 1
def summary(self):
return "%d run, 0 failed" % self.runCount必須實際呼叫這個新方法:
def run(self):
result= TestResult()
result.testStarted()
self.setUp()
method = getattr(self, self.name)
method()
self.tearDown()
return result測試失敗的計數#
可以用同樣方式將失敗次數的常數字串 "0" 變成變數,但目前的測試不要求這樣做。所以改寫另一個測試:
def testFailedResult(self):
test= WasRun("testBrokenMethod")
result= test.run()
assert("1 run, 1 failed", result.summary)其中:
def testBrokenMethod(self):
raise Exception待辦清單更新:
Invoke test methodInvoke setUp firstInvoke tearDown afterward- Invoke tearDown even if the test method fails
- Run multiple tests
Report collected resultsLog string in WasRun- Report failed tests
第一個注意到的問題是我們沒有捕捉 WasRun.testBrokenMethod 拋出的例外。我們希望捕捉例外並在結果中記下測試失敗。先把這個測試擱置。
本章回顧#
- 用 Fake Implementation 開始,然後透過用變數取代常數逐步實體化
- 寫了另一個測試
- 當那個測試失敗時,寫了一個更小規模的測試來支撐失敗測試的運作