python單元測試unittest實例詳解

轉自:http://blog.csdn.net/five3/article/details/7104466python

 

 

單元測試做爲任何語言的開發者都應該是必要的,由於時隔數月後再回來調試本身的複雜程序時,其實也是很崩潰的事情。雖然會很快熟悉內容,可是修改和調試將是一件痛苦的事情,若是你在修改了代碼後出現問題的話,而單元測試能夠幫助咱們很快準確的定位到問題的位置,出現問題的模塊和單元。因此這是一件很愉快的事情,由於咱們知道其它修改或沒有修改的地方仍然是正常工做的,而咱們目前的惟一問題就是搞定眼前這個有點問題的「傢伙」。因此工做會在輕鬆中開始,而且很快將會結束,由於你已經知道不少信息了。框架

 

單元測試天然是對程序中最小的可測試模塊--函數來進行測試;由於單元測試的對象是函數,也就是說你得被測試對象必定要有輸出結果,哪怕就是異常輸出,也得有輸出,以便單元測試模塊可以捕獲返回值,而且與預期值進行比較,從而得出測試經過與否。函數

 

單元測試的加載方式有2種:一種是經過unittest.main()來啓動單元測試的測試模塊;一種是添加到testsuite集合中再加載全部的被測試對象,而testsuit裏存放的就是單元測試的用例,下面分別列出了2種方法的使用。單元測試

1.1 測試模塊中的函數:測試

被測模塊:ui

[python]  view plain  copy
 
  1. #!/usr/bin/env python  
  2. #encoding: utf-8  
  3.       
  4. def sum( x, y):  
  5.         return x+y  
  6.       
  7.       
  8. def sub( x, y):  
  9.         return x-y   

單元測試模塊:spa

[python]  view plain  copy
 
  1. #!/usr/bin/env python  
  2. #encoding: utf-8  
  3.   
  4. import unittest  
  5. import myclass  
  6.   
  7. class mytest(unittest.TestCase):  
  8.       
  9.     ##初始化工做  
  10.     def setUp(self):  
  11.         pass  
  12.       
  13.     #退出清理工做  
  14.     def tearDown(self):  
  15.         pass  
  16.       
  17.     #具體的測試用例,必定要以test開頭  
  18.     def testsum(self):  
  19.         self.assertEqual(myclass.sum(1, 2), 2, 'test sum fail')  
  20.           
  21.           
  22.     def testsub(self):  
  23.         self.assertEqual(myclass.sub(2, 1), 1, 'test sub fail')     
  24.           
  25.           
  26. if __name__ =='__main__':  
  27.     unittest.main()  

測試結果:【F表示一個fail, F前的點表示一個經過,有E的話表示程序自身異常】.net

[python]  view plain  copy
 
  1. .F  
  2. ======================================================================  
  3. FAIL: testsum (__main__.mytest)  
  4. ----------------------------------------------------------------------  
  5. Traceback (most recent call last):  
  6.   File "C:\Users\xiaowu\workspace\mypython\unitTest.py", line 19, in testsum  
  7.     self.assertEqual(myclass.sum(1, 2), 2, 'test sum fail')  
  8. AssertionError: test sum fail  
  9.   
  10. ----------------------------------------------------------------------  
  11. Ran 2 tests in 0.001s  
  12.   
  13. FAILED (failures=1)  

1.2 測試模塊類中的函數:命令行

被測模塊:調試

[python]  view plain  copy
 
  1. #!/usr/bin/env python  
  2. #encoding: utf-8  
  3.   
  4. class myclass:  
  5.     def __init__(self):  
  6.         pass  
  7.       
  8.       
  9.     def sum(self, x, y):  
  10.         return x+y  
  11.       
  12.       
  13.     def sub(self, x, y):  
  14.         return x-y   

單元測試模塊:

[python]  view plain  copy
 
  1. #!/usr/bin/env python  
  2. #encoding: utf-8  
  3.   
  4. import unittest  
  5. import myclass  
  6.   
  7. class mytest(unittest.TestCase):  
  8.       
  9.     ##初始化工做  
  10.     def setUp(self):  
  11.         self.tclass = myclass.myclass()   ##實例化了被測試模塊中的類  
  12.       
  13.     #退出清理工做  
  14.     def tearDown(self):  
  15.         pass  
  16.       
  17.     #具體的測試用例,必定要以test開頭  
  18.     def testsum(self):  
  19.         self.assertEqual(self.tclass.sum(1, 2), 3)  
  20.           
  21.           
  22. if __name__ =='__main__':  
  23.     unittest.main()  

運行結果:

[python]  view plain  copy
 
  1. .  
  2. ----------------------------------------------------------------------  
  3. Ran 1 test in 0.000s  
  4.   
  5. OK  

這種方式執行單個測試文件時使用-v參數能夠得到更多的測試結果信息。如:mytest.py -v 

 

2 加載測試套件

好吧,在運用測試套件進行單元測試以前,我想仍是稍微研究一下unittest模塊的內容有哪些,其大概的運行方式是什麼樣的。然後在給出根據各類狀況如何制定單元測試套件。

首先,天然是查看unittest模塊有哪些成員啦!

[python]  view plain  copy
 
  1. >>import unittest  
  2. >>dir(unittest)  
  3. ['FunctionTestCase', 'TestCase', 'TestLoader', 'TestProgram', 'TestResult', 'Tes  
  4. tSuite', 'TextTestRunner', '_CmpToKey', '_TextTestResult', '_WritelnDecorator',  
  5. '__all__', '__author__', '__builtins__', '__doc__', '__email__', '__file__', '__  
  6. metaclass__', '__name__', '__package__', '__unittest', '__version__', '_makeLoad  
  7. er', '_strclass', 'defaultTestLoader', 'findTestCases', 'getTestCaseNames', 'mai  
  8. n', 'makeSuite', 'os', 'sys', 'time', 'traceback', 'types']  

能夠看到其自身的成員也不是不少,大概包括有:
['FunctionTestCase', 'TestCase', 'TestLoader', 'TestProgram', 'TestResult',
 'TestSuite','TextTestRunner', '_CmpToKey', '_TextTestResult', '_WritelnDecorator',
 'defaultTestLoader','findTestCases', 'getTestCaseNames', 'main', 'makeSuite']
 
 好吧,咱們大概看看具體都是幹什麼的

[python]  view plain  copy
 
  1. >>memblist = ['FunctionTestCase', 'TestCase', 'TestLoader', 'TestProgram', 'TestResult',\  
  2. 'TestSuite','TextTestRunner', 'defaultTestLoader','findTestCases', 'getTestCaseNames', \  
  3. 'main', 'makeSuite']  
  4. >>for memb in memblist:  
  5. ..  cur = getattr(unittest, memb)  
  6. ..  print help(cur)  

 'FunctionTestCase':函數測試用例,即給一個函數做爲參數,返回一個testcase實例,可選參數有set-up,tear-down方法
 'TestCase':全部測試用例的基本類,給一個測試方法的名字,返回一個測試用例實例
 'TestLoader':測試用例加載器,其包括多個加載測試用例的方法。返回一個測試套件
 loadTestsFromModule(self, module)--根據給定的模塊實例來獲取測試用例套件
 loadTestsFromName(self, name, module=None)
 --根據給定的字符串來獲取測試用例套件,字符串能夠是模塊名,測試類名,測試類中的測試方法名,或者一個可調用的是實例對象
 這個實例對象返回一個測試用例或一個測試套件
 loadTestsFromNames(self, names, module=None) --和上面功能相同,只不過接受的是字符串列表
 loadTestsFromTestCase(self, testCaseClass)--根據給定的測試類,獲取其中的全部測試方法,並返回一個測試套件
'TestProgram':命令行進行單元測試的調用方法,做用是執行一個測試用例。其實unittest.main()方法執行的就是這個命令,
而這個類實例時默認加載當前執行的做爲測試對象,
原型爲 __init__(self, module='__main__', defaultTest=None, argv=None, testRunner=xx, testLoader=xx)
其中module='__main__'就是默認加載自身
'TestResult':測試用例的結果保存實例,一般有測試框架調用
 'TestSuite':組織測試用例的實例,支持測試用例的添加和刪除,最終將傳遞給testRunner進行測試執行
 'TextTestRunner':進行測試用例執行的實例,其中Text的意思是以文本形式顯示測試結果。顯示測試名稱,即完成的測試結果,其過同執行單元測試腳本時添加-v參數
 'defaultTestLoader':其實就是TestLoader
 'findTestCases', 'getTestCaseNames':這個2個就不用解釋了
 'main': 其實就是TestProgram
 'makeSuite':一般是由單元測試框架調用的,用於生產testsuite對象的實例
 
 至此,咱們知道了。其實整個單元測試框架的邏輯出來了。分三步走:第一步testloader根據傳入的參數得到相應的測試用例,即對應具體的測試方法,
 而後makesuite在把全部的測試用例組裝成testsuite,最後把testsiute傳給testrunner進行執行。
 而咱們一般執行的unittest.main(),其實就是unittest.testprom方法,其執行的功能就是上面分析的三步,在第一步中其傳入的參數是自身的模塊__main__;
 在第二步中把自身模塊中的全部測試類中中的測試方法提取出來,並生成測試套件;最後再把測試套件傳遞給testrunner進行具體的測試。
 
 最後給出一個完整的單元測試組織代碼,把該代碼放到單元測試用例文件的同一個目錄後執行該腳本,便可執行全部的測試用例文件。
 【測試用例文件必須爲test開頭,如:testxxx.py, 固然這個文件自己是一個單元測試的文件】

[python]  view plain  copy
 
    1. #!/usr/bin/env python  
    2. #encoding: utf-8  
    3. #該代碼源自深刻python  
    4. import unittest  
    5. import myclass  
    6. import re  
    7. import os  
    8. import sys  
    9.   
    10.   
    11. def testAllinCurrent():  
    12.     path = os.path.abspath(os.path.dirname(sys.argv[0]))     
    13.     files = os.listdir(path)                                 
    14.     test = re.compile("test\.py{1}quot;, re.IGNORECASE)            
    15.     files = filter(test.search, files)                       
    16.     filenameToModuleName = lambda f: os.path.splitext(f)[0]  
    17.     moduleNames = map(filenameToModuleName, files)           
    18.     modules = map(__import__, moduleNames)     
    19.                     
    20.     load = unittest.defaultTestLoader.loadTestsFromModule    
    21.     return unittest.TestSuite(map(load, modules))  
    22.   
    23. if __name__ == "__main__":                     
    24.     unittest.main(defaultTest="regressionTest")  
相關文章
相關標籤/搜索