19.unittest原理

單元測試
單元測試(unit testing)是指對軟件中的最小可測試單元進行檢查和驗證。對於單元測試中單元的含義,通常來講,要根據實際狀況去斷定其具體含義,如C語言中單元指一個函數,Java裏單元指一個類,圖形化的軟件中能夠指一個窗口或一個菜單等。總的來講,單元就是人爲規定的最小的
被測功能模塊。

html

unittest運行原理

 

 

TestCase:一個TestCase的實例就是一個測試用例。什麼是測試用例呢?就是一個完整的測試流程,包括測試前準備環境的搭建(setUp),執行測試代碼(run),以及測試後環境的還原(tearDown)。元測試(unit test)的本質也就在這裏,一個測試用例是一個完整的測試單元,經過運行這個測試單元,能夠對某一個問題進行驗證。python

TestSuite:而多個測試用例集合在一塊兒,就是TestSuite,並且TestSuite也能夠嵌套TestSuite。 TestLoader是用來加載TestCase到TestSuite中的,其中有幾個loadTestsFrom__()方法,就是從各個地方尋找TestCase,建立它們的實例,而後add到TestSuite中,再返回一個TestSuite實例。git

TextTestRunner:extTestRunner是來執行測試用例的,其中的run(test)會執行TestSuite/TestCase中的run(result)方法。測試的結果會保存到TextTestResult實例中,包括運行了多少測試用例,成功了多少,失敗了多少等信息。github

fixture:而對一個測試用例環境的搭建和銷燬,是一個fixture。
一個class繼承了unittest.TestCase,即是一個測試用例,但若是其中有多個以 test 開頭的方法,那麼每有一個這樣的方法,在load的時候便會生成一個TestCase實例,如:一個class中有四個test_xxx方法,最後在load到suite中時也有四個測試用例。框架

在每個測試用例中能夠重寫 如下函數
setUp()該測試用例執行前的設置工做、
tearDown()該測試用例執行後的清理工做、
setUpClass()全部測試用例前的設置工做、
tearDownClass()全部測試用例執行後的清洗工做less

在每個測試用例中能夠經過skip,skipIf,skipUnless裝飾器跳過某個測試函數,或者用TestCase.skipTest方法跳過測試函數。ide

流程:寫好TestCase,而後由TestLoader加載TestCase到TestSuite,而後由TextTestRunner來運行TestSuite,運行的結果保存在TextTestResult中,咱們經過命令行或者unittest.main()執行時,main會調用TextTestRunner中的run來執行,或者咱們能夠直接經過TextTestRunner來執行用例。函數

注意說明:單元測試

一、TestLoader加載TestCase到TestSuite能夠經過TestSuite實例對象的addTest()和addTests()方法向suite中添加case或suite測試

二、在Runner執行時,默認將執行結果輸出到控制檯,咱們能夠設置其輸出到文件,在文件中查看結果(你可能據說過HTMLTestRunner,是的,經過它能夠將結果輸出到HTML中,生成漂亮的報告,它跟TextTestRunner是同樣的,從名字就能看出來,這個咱們後面再說)。

三、在進行測試時能夠傳遞verbosity參數,用以控制執行結果的輸出,0 是簡單報告、1 是通常報告、2 是詳細報告。

案例
業務函數

這裏咱們隨意寫幾個業務函數,表示咱們將要進行測試的功能函數。將功能函數文件存儲成mathfunc.py

def add(a, b):
return a+b

def minus(a, b):
return a-b

def multi(a, b):
return a*b

def divide(a, b):
return a/b

TestCase測試用例
咱們經過測試用例用代碼來實現每個測試的詳細過程和針對測試目標要測試的內容。同目錄下建立test_mathfunc.py

import unittest
from mathfunc import *

 

class TestMathFunc(unittest.TestCase):

# TestCase基類方法,全部case執行以前自動執行
@classmethod
def setUpClass(cls):
print("這裏是全部測試用例前的準備工做")

# TestCase基類方法,全部case執行以後自動執行
@classmethod
def tearDownClass(cls):
print("這裏是全部測試用例後的清理工做")

# TestCase基類方法,每次執行case前自動執行
def setUp(self):
print("這裏是一個測試用例前的準備工做")

# TestCase基類方法,每次執行case後自動執行
def tearDown(self):
print("這裏是一個測試用例後的清理工做")

@unittest.skip("我想臨時跳過這個測試用例.")
def test_add(self):
self.assertEqual(3, add(1, 2))
self.assertNotEqual(3, add(2, 2)) # 測試業務方法add

def test_minus(self):
self.skipTest('跳過這個測試用例')
self.assertEqual(1, minus(3, 2)) # 測試業務方法minus

def test_multi(self):
self.assertEqual(6, multi(2, 3)) # 測試業務方法multi

def test_divide(self):
self.assertEqual(2, divide(6, 3)) # 測試業務方法divide
self.assertEqual(2.5, divide(5, 2))

if __name__ == '__main__':
unittest.main(verbosity=2)

注意:

skip裝飾器一共有三個 unittest.skip(reason)、unittest.skipIf(condition,reason)、unittest.skipUnless(condition,reason),skip無條件跳過,skipIf當condition爲True時跳過,skipUnless當condition爲False時跳過。

每一個測試方法均以 test 開頭,不然是不被unittest識別的。

其實每個test開頭的方法都會加載爲獨立的測試用例。

在unittest.main()中加 verbosity 參數能夠控制輸出的錯誤報告的詳細程度,默認是 1,若是設爲 0,則不輸出每一用例的執行結果。若是參數爲2則表示輸出詳細結果。

TestSuite測試組
TestSuite用來控制多個測試用例和多個測試文件之間的測試順序。(這裏的示例中的幾個測試方法並無必定關係,但以後你寫的用例可能會有前後關係,須要先執行方法A,再執行方法B)

咱們添加到TestSuite中的case是會按照添加的順序執行的。

下面咱們就來試下將測試用例加載到測試組中。進行測試並將測試結果輸出。
下面的代碼存儲成

import unittest
from test_mathfunc import TestMathFunc
from HTMLTestRunner import HTMLTestRunner

if __name__ == '__main__':
suite = unittest.TestSuite()

tests = [TestMathFunc("test_add"), TestMathFunc("test_minus"), TestMathFunc("test_divide")] # 添加測試用例列表
suite.addTests(tests) # 將測試用例列表添加到測試組中
suite.addTest(TestMathFunc("test_multi")) # 直接用addTest方法添加單個TestCase
# 用addTests + TestLoader。不過用TestLoader的方法是沒法對case進行排序的
# loadTestsFromName(),傳入'模塊名.TestCase名'
suite.addTests(unittest.TestLoader().loadTestsFromName('test_mathfunc.TestMathFunc'))
suite.addTests(unittest.TestLoader().loadTestsFromNames(['test_mathfunc.TestMathFunc'])) # loadTestsFromNames(),相似,傳入列表

# loadTestsFromTestCase(),傳入TestCase
suite.addTests(unittest.TestLoader().loadTestsFromTestCase(TestMathFunc))

# suite中也能夠套suite

# 將測試結果輸出到測試報告中
# with open('UnittestTextReport.txt', 'a') as f:
# runner = unittest.TextTestRunner(stream=f, verbosity=2)
# runner.run(suite)

# 將測試結果輸出到測試報告html中
# with open('HTMLReport.html', 'w') as f:
# runner = HTMLTestRunner(stream=f,
# title='MathFunc Test Report',
# description='generated by HTMLTestRunner.',
# verbosity=2
# )
# runner.run(suite)

# 直接將結果輸出到控制檯
runner = unittest.TextTestRunner(verbosity=2)
runner.run(suite)

測試報告
上面咱們實現了將測試結果輸出到功控制檯、txt、html三種形式。其中html的輸出須要加載HTMLTestRunner.py模塊。下載地址:https://github.com/626626cdllp/Test/blob/master/python-unittest/HTMLTestRunner.py

三種輸出結果只能選擇一種,不能所有選擇。

控制檯輸出:

 

 

txt輸出:

 

 

html輸出:


總結一下:unittest是Python自帶的單元測試框架,咱們能夠用其來做爲咱們自動化測試框架的用例組織執行框架。unittest的流程:寫好TestCase,而後由TestLoader加載TestCase到TestSuite,而後由TextTestRunner來運行TestSuite,運行的結果保存在TextTestResult中,咱們經過命令行或者unittest.main()執行時,main會調用TextTestRunner中的run來執行,或者咱們能夠直接經過TextTestRunner來執行用例。一個class繼承unittest.TestCase便是一個TestCase,其中以 test 開頭的方法在load時被加載爲一個真正的TestCase。verbosity參數能夠控制執行結果的輸出,0 是簡單報告、1 是通常報告、2 是詳細報告。能夠經過addTest和addTests向suite中添加case或suite,能夠用TestLoader的loadTestsFrom__()方法。用 setUp()、tearDown()、setUpClass()以及 tearDownClass()能夠在用例執行前佈置環境,以及在用例執行後清理環境咱們能夠經過skip,skipIf,skipUnless裝飾器跳過某個case,或者用TestCase.skipTest方法。參數中加stream,能夠將報告輸出到文件:能夠用TextTestRunner輸出txt報告,以及能夠用HTMLTestRunner輸出html報告。

相關文章
相關標籤/搜索