import unittest class UTest(unittest.TestCase): def test_upper(self): self.assertEqual('foo'.upper(), 'FOO') def test_isupper(self): self.assertTrue('FOO'.isupper()) self.assertFalse('Foo'.isupper()) if __name__ == '__main__': unittest.main()
注:
0. unnitest 是 python 自帶的庫,不需要額外的安裝即可用
1. 測試用例 (testcase) 都是由 unittest.TestCase 類創建的,對應的 test 開頭的 測試方法, 如上例的 test_upper
2.
setUp() and
tearDown() 方法用來定義一些初始化和清理的 指令, 這兩個方法分別在 每個測試用例 開始前和結束后執行。
如果只要在所有的測試用例之前和之后只執行一次,則用 setUpClass() 和 tearDownClass()
如果所有的測試用例都需要執行的一些共同步驟可以放在setUp(), 如果做一次就對所有的測試用例生效的就放在setUpClass(),譬如登陸(coolie對所有的測試用例都可以共享)
setupClass() 和 tearDownClass() 必需加上裝飾器 @classmethod, 否則會出錯。 setUp() 和
tearDown() 則不用。
3. unittest.main()提供了一個測試腳本的命令行接口。
4. 其他途徑運行測試用例有:
suite = unittest.TestLoader().loadTestsFromTestCase(UTest)
unittest.TextTestRunner(verbosity=2).run(suite)
5. 命令行: python -m unittest test_module.TestClass 和 python -m unittest test_module.TestClass.test_method
如上面的例子:python -m unittest UTest.UTest
python -m unittest UTest.UTest.test_upper
還可以傳一個 -v 標志 來獲取 更詳細的測試結果:python -m unittest -v test_module
如上例: D:\Python>python -m unittest -v UTest
結果: test_isupper (UTest.UTest) ... ok
test_upper (UTest.UTest) ... ok
6. 要運行一個class 里的 所有測試用例(所有test開頭的方法),有以下幾種方法:
A. unittest.main() 對應的命令行 是 ptyon module.py
B. suite = unittest.TestLoader().loadTestsFromTestCase(UTest)
unittest.TextTestRunner(verbosity=2).run(suite)
對應的命令行是 python -m unittest test_module.TestClass
C. 新建一個TestSuite 實例,然后一個一個的把所有的測試用例加到這個測試集,最后通過 TextTestRunner 這個對象的run方法運行測試集
如,此方法比較繁瑣,加入有50個測試用例,需要手動的把50個用例一個一個的加到TestSuite 里
suite = unittest.TestSuite() suite.addTest(UTest('test_isupper')) suite.addTest(UTest('test_upper')) runner = unittest.TextTestRunner() runner.run(suite)
但是,如果是class 里只有一個測試方法,但測試時需要不同的測試數據,C 的方法派上用場:
a.首先,重寫TestCase類的構造函數,把input 作為構造函數的參數(由於測試方法不能傳參數,所以只能在構造函數里傳入需要的input),如:
def __init__(self, marketcode, stockcode, stocktype,methodName): super(Comparison, self).__init__(methodName) self.marketcode = marketcode self.stockcode = stockcode self.stocktype = stocktype
b. 然后是測試用例方法對input的引用
def test_getPriceInfo(self): stime = Utils.getTimestamp() mkt_price = ParseResponse.getMarketLastPrice(self.marketcode,self.stockcode,self.stocktype) position_price = ParseResponse.getPositionLastPrice(self.loginKey,self.loginCookie,self.stockcode,self.marketcode) self.infoDir["timestamp"] = stime self.infoDir["ticker"] = self.marketcode + self.stockcode self.infoDir["postionprice"] = position_price self.infoDir["marketprice"] = mkt_price AlertRecorder.cmpMktPosition(self.infoDir) print self.infoDir
c. 最后在class 外定義一個運行的方法,其中 Comparison(stockInfo[0],stockInfo[1],stockInfo[2], "test_getPriceInfo") 即是創建一個測試類示例,test_getPriceInfo為測試用例方法名,這個是 unittest.TestCase類需要的參數。
def run(): suite = unittest.TestSuite() stockInfoList = Scheduler.get_mktPostion_stocks() for stockInfo in stockInfoList: suite.addTest(Comparison(stockInfo[0],stockInfo[1],stockInfo[2], "test_getPriceInfo")) runner = unittest.TextTestRunner() runner.run(suite)
綜上,封裝起來為:
A. .main(verbosity=2), 其中verbosity=2 是使得結果輸出時更詳細
B.
def run(): suite = unittest.TestLoader().loadTestsFromTestCase(testCaseClassName) runner = unittest.TextTestRunner(verbosity=2) runner.run(suite)
C.
def run(): suite = unittest.TestSuite() suite.addTest(testCaseClassName('test_method')) runner = unittest.TextTestRunner(verbosity=2) runner.run(suite)
注意:上述三個運行測試的方法,在IDE上的輸出結果有點差別。A 和 C 輸出的結果:
set up for class
test_isupper (__main__.UTest) ... ok
test_sum (__main__.UTest) ... ok
test_upper (__main__.UTest) ... ok
而B輸出結果為:
test_sum (__main__.UTest) ... ok
test_upper (__main__.UTest) ... ok
set up for class
test_isupper (__main__.UTest) ... ok
優先還是用 unittest.main() 和 unittest.TextTestRunner().run(unittest.TestLoader().loadTestsFromTestCase(testCaseClassName))
7. 如果要跳過測試,則可以用到 裝飾器 @unittest.skip("reason") 和 @unittest.skipIf(condition,'reason'). 如果是針對個別測試用例,則在 測試用例方法加裝飾器。如果需要跳過所有的測試(譬如節假日)則在 setUpClass 上加裝飾器。這種情況下得注意兩個裝飾器的先后順序,先@classmethod 后 @unittest.skipIf()。如:
@classmethod
@unittest.skipIf(True, "To skip the test")
def setUpClass(cls):
print 'set up for class'
另外,setUp()也可以跳過所有的測試,不過和 setUpClass 有區別: setUpClass 是一次性跳過所有的測試,運行結果顯示運行0個測試: Ran 0 tests in 0.000s OK (skipped=1)
但setUp 則是每個測試用例都跳過運行,顯示結果是跑了N 個,跳過N 個:
test_isupper (__main__.UTest) ... skipped '...reason...'
test_sum (__main__.UTest) ... skipped '...reason...'
test_upper (__main__.UTest) ... skipped '...reason...'
8. 如果要獲得測試結果中運行的測試用例的總數以及成功和失敗的總數,可以從unittest.TestResult 中獲得 失敗的個數和運行的總數
suite = unittest.TestLoader().loadTestsFromTestCase(UTest) runner = unittest.TextTestRunner(verbosity=2) result = runner.run(suite) print result.testsRun #運行的測試用例的總數 print len(result.failures) #失敗的測試用例的數目
關於 failures: A list containing 2-tuples of TestCase instances and strings holding formatted tracebacks. Each tuple represents a test where a failure was explicitly
signalled using the TestCase.assert*() methods.