一.概念
unittest中最核心的四個概念是:test case, test suite, test runner, test fixture。
test case,:一個TestCase的執行個體就是一個測試用例
test suite:而多個測試用例集合在一起,就是TestSuite,而且TestSuite也可以嵌套TestSuite
testLoader是将TestCase加載到TestSuite裡,用loadTestsFrom__()等幾個方法,找到testcase建立它們的執行個體,然後add到TestSuite中,再傳回一個TestSuite執行個體。
test runner:TextTestRunner是來執行測試用例的,其中的run(test)會執行TestSuite/TestCase中的run(result)方法。 測試的結果會儲存到TextTestResult執行個體中,包括運作了多少測試用例,成功了多少,失敗了多少等資訊。
test fixture:而對一個測試用例環境的搭建和銷毀,是一個fixture。
流程描述:寫好TestCase,然後由TestLoader加載TestCase到TestSuite,然後由TextTestRunner來運作TestSuite,運作的結果儲存在TextTestResult中,我們通過指令行或者unittest.main()執行時,main會調用TextTestRunner中的run來執行,或者我們可以直接通過TextTestRunner來執行用例。這裡加個說明,在Runner執行時,預設将執行結果輸出到控制台,我們可以設定其輸出到檔案,在檔案中檢視結果(通過HTMLTestRunner可以将結果輸出到HTML中,生成漂亮的報告,它跟TextTestRunner是一樣的,從名字就能看出來,這個我們後面再說)
二.執行個體運作
# -*- coding: utf-8 -*-
import unittest
from mathfunc import *
class TestMathFunc(unittest.TestCase):
"""Test mathfuc.py"""
def setUp(self):
print "do something before test.Prepare environment."
def tearDown(self):
print "do something after test.Clean up."
def test_add(self):
"""Test method add(a, b)"""
print "add"
self.assertEqual(3, add(1, 2))
self.assertNotEqual(3, add(2, 2))
def test_minus(self):
"""Test method minus(a, b)"""
print "minus"
self.assertEqual(1, minus(3, 2))
def test_multi(self):
"""Test method multi(a, b)"""
print "multi"
self.assertEqual(6, multi(2, 3))
def test_divide(self):
"""Test method divide(a, b)"""
print "divide"
self.assertEqual(2, divide(6, 3))
self.assertEqual(2.5, divide(5, 2))
test fixture之setUp() tearDown()
上面整個測試基本跑了下來,但可能會遇到點特殊的情況:如果我的測試需要在每次執行之前準備環境,或者在每次執行完之後需要進行一些清理怎麼辦?比如執行前需要連接配接資料庫,執行完成之後需要還原資料、斷開連接配接。總不能每個測試方法中都添加準備環境、清理環境的代碼吧。
我們添加了
setUp()
和
tearDown()
兩個方法(其實是重寫了TestCase的這兩個方法),這兩個方法在每個測試方法執行前以及執行後執行一次,setUp用來為測試準備環境,tearDown用來清理環境,已備之後的測試。
三.将結果輸出到檔案中
用例組織好了,但結果隻能輸出到控制台,這樣沒有辦法檢視之前的執行記錄,我們想将結果輸出到檔案。很簡單,看示例:
修改test_suite.py:
# -*- coding: utf-8 -*-
import unittest
from test_mathfunc import TestMathFunc
if __name__ == '__main__':
suite = unittest.TestSuite()
suite.addTests(unittest.TestLoader().loadTestsFromTestCase(TestMathFunc))
with open('UnittestTextReport.txt', 'a') as f:
runner = unittest.TextTestRunner(stream=f, verbosity=2)
runner.run(suite)
四.輸出美觀的測試報告----HTMLTestRunner
HTMLTestRunner是一個第三方的unittest HTML報告庫,首先我們下載下傳HTMLTestRunner.py,并放到目前目錄下,或者你的’C:\Python27\Lib’下,就可以導入運作了。
test_suite.py
:
# -*- coding: utf-8 -*-
import unittest
from test_mathfunc import TestMathFunc
from HTMLTestRunner import HTMLTestRunner
if __name__ == '__main__':
suite = unittest.TestSuite()
suite.addTests(unittest.TestLoader().loadTestsFromTestCase(TestMathFunc))
with open('HTMLReport.html', 'w') as f:
runner = HTMLTestRunner(stream=f,
title='MathFunc Test Report',
description='generated by HTMLTestRunner.',
verbosity=2
)
runner.run(suite)
運作後結果:
ok test_add (test_mathfunc.TestMathFunc)
F test_divide (test_mathfunc.TestMathFunc)
ok test_minus (test_mathfunc.TestMathFunc)
ok test_multi (test_mathfunc.TestMathFunc)
Time Elapsed: 0:00:00.001000
并且輸出了HTML測試報告,
HTMLReport.html
五.跳過某個case-skip裝飾器
skip裝飾器一共有三個
unittest.skip(reason)
、
unittest.skipIf(condition, reason)
、
unittest.skipUnless(condition, reason)
,skip無條件跳過,skipIf當condition為True時跳過,skipUnless當condition為False時跳過。
- skip裝飾器
...
class TestMathFunc(unittest.TestCase):
"""Test mathfuc.py"""
...
@unittest.skip("I don't want to run this case.")
def test_divide(self):
"""Test method divide(a, b)"""
print "divide"
self.assertEqual(2, divide(6, 3))
self.assertEqual(2.5, divide(5, 2))
執行:
...
test_add (test_mathfunc.TestMathFunc)
Test method add(a, b) ... ok
test_divide (test_mathfunc.TestMathFunc)
Test method divide(a, b) ... skipped "I don't want to run this case."
test_minus (test_mathfunc.TestMathFunc)
Test method minus(a, b) ... ok
test_multi (test_mathfunc.TestMathFunc)
Test method multi(a, b) ... ok
----------------------------------------------------------------------
Ran 4 tests in 0.000s
OK (skipped=1)
可以看到總的test數量還是4個,但divide()方法被skip了。
2.TestCase.skipTest()方法
...
class TestMathFunc(unittest.TestCase):
"""Test mathfuc.py"""
...
def test_divide(self):
"""Test method divide(a, b)"""
self.skipTest('Do not run this.')
print "divide"
self.assertEqual(2, divide(6, 3))
self.assertEqual(2.5, divide(5, 2))
輸出:
...
test_add (test_mathfunc.TestMathFunc)
Test method add(a, b) ... ok
test_divide (test_mathfunc.TestMathFunc)
Test method divide(a, b) ... skipped 'Do not run this.'
test_minus (test_mathfunc.TestMathFunc)
Test method minus(a, b) ... ok
test_multi (test_mathfunc.TestMathFunc)
Test method multi(a, b) ... ok
----------------------------------------------------------------------
Ran 4 tests in 0.001s
OK (skipped=1)
效果跟上面的裝飾器一樣,跳過了divide方法。
六.總結
六.總結
總結一下:
- unittest是Python自帶的單元測試架構,我們可以用其來作為我們自動化測試架構的用例組織執行架構。
- unittest的流程:寫好TestCase,然後由TestLoader加載TestCase到TestSuite,然後由TextTestRunner來運作TestSuite,運作的結果儲存在TextTestResult中,我們通過指令行或者unittest.main()執行時,main會調用TextTestRunner中的run來執行,或者我們可以直接通過TextTestRunner來執行用例。
- 一個class繼承unittest.TestCase即是一個TestCase,其中以
開頭的方法在load時被加載為一個真正的TestCase。test
- verbosity參數可以控制執行結果的輸出, 是簡單報告、
是一般報告、1
是詳細報告。2
- 可以通過addTest和addTests向suite中添加case或suite,可以用TestLoader的loadTestsFrom__()方法。
- 用
、setUp()
、tearDown()
以及setUpClass()
可以在用例執行前布置環境,以及在用例執行後清理環境tearDownClass()
- 我們可以通過skip,skipIf,skipUnless裝飾器跳過某個case,或者用TestCase.skipTest方法。
- 參數中加stream,可以将報告輸出到檔案:可以用TextTestRunner輸出txt報告,以及可以用HTMLTestRunner輸出html報告。
來自原文轉載位址:https://huilansame.github.io/huilansame.github.io/archivers/python-unittest