tearDown 的需求#
待辦清單:
Invoke test methodInvoke setUp first- Invoke tearDown afterward
- Invoke tearDown even if the test method fails
- Run multiple tests
- Report collected results
有時測試需要在 setUp() 中配置外部資源。為了維持測試的獨立性,配置了外部資源的測試需要在完成前釋放它們,或許透過 tearDown() 方法。
從旗標到日誌#
最直覺的做法是再引入一個旗標來測試 tearDown。但那些旗標已經開始令人困擾,而且它們忽略了方法的一個重要面向:setUp() 在 test method 之前呼叫,tearDown() 在之後呼叫。
flowchart LR
A["setUp()"] --> B["testMethod()"]
B --> C["tearDown()"]
style A fill:#4CAF50,color:#fff
style B fill:#2196F3,color:#fff
style C fill:#FF9800,color:#fff作者決定改變測試策略——改用一個**日誌字串(log)**記錄被呼叫的方法。透過持續附加到日誌,可以保留方法被呼叫的順序。
新增待辦項目:
Invoke test methodInvoke setUp first- Invoke tearDown afterward
- Invoke tearDown even if the test method fails
- Run multiple tests
- Report collected results
- Log string in WasRun
在 setUp 中初始化日誌:
def setUp(self):
self.wasRun= None
self.wasSetUp= 1
self.log= "setUp "修改 testSetUp 改為檢查日誌而非旗標:
def testSetUp(self):
self.test.run()
assert("setUp " == self.test.log)接著可以刪除 wasSetUp 旗標。在 testMethod 中也記錄到日誌:
def testMethod(self):
self.wasRun= 1
self.log= self.log + "testMethod "這會讓 testSetUp 失敗,因為實際日誌內容變成 "setUp testMethod "。修改預期值:
def testSetUp(self):
self.test.run()
assert("setUp testMethod " == self.test.log)現在這個測試同時做了兩個測試的工作,因此可以刪除 testRunning 並重新命名 testSetUp:
def testTemplateMethod(self):
test= WasRun("testMethod")
test.run()
assert("setUp testMethod " == test.log)補充: 注意
WasRun實例只在一個地方使用了,所以之前把它放到setUp的手法必須撤回。基於少量使用就做重構、之後又得撤銷,這是很常見的。有些人會等到三、四次使用後才重構。作者偏好把思考力用在設計上,反射性地做重構而不擔心是否需要立即撤銷。
實作 tearDown#
準備好測試 tearDown() 了——先寫測試:
def testTemplateMethod(self):
test= WasRun("testMethod")
test.run()
assert("setUp testMethod tearDown " == test.log)測試失敗。讓它通過很簡單:
def run(self, result):
result.testStarted()
self.setUp()
method = getattr(self, self.name)
method()
self.tearDown()def setUp(self):
self.log= "setUp "
def testMethod(self):
self.log= self.log + "testMethod "
def tearDown(self):
self.log= self.log + "tearDown "出乎意料地,錯誤不是出在 WasRun,而是在 TestCaseTest——TestCase 中缺少空的 tearDown() 實作:
def tearDown(self):
pass技巧: 這次我們從使用正在開發的框架本身獲得了回饋價值。框架自身的測試發現了遺漏的預設實作。
待辦清單更新:
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
本章回顧#
- 將測試策略從旗標重構為日誌
- 使用新的日誌策略測試並實作了
tearDown() - 發現一個問題並大膽地直接修復,而非回退(這是個好主意嗎?)