Python unittest 學習

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 的方法派上用場:html

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類須要的參數。python

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.
相關文章
相關標籤/搜索