選擇
語言選擇
本次個人作業我選擇的語言是Python,了解學習Python有一段時間了但是一直沒有練習,所以這次玩蛇,使用的版本是Python3.6。
開發工具選擇
我選擇的IDE是Pycharm,個人認為Pycharm是一款不錯的Py開發工具,用起來得心應手,unittset是py自帶的包不需要安裝直接引用即可,方便快捷。開發工具截圖如下。
Python單元測試框架unittest
unittest簡介
TestCase(測試用例)
一個testcase就是一個測試用例,包括測試前環境的搭建setUp,執行測試代碼run,測試后環境的還原tearDown,是一個完整的測試單元。
TestSuite(測試套件)
多個testcase的集合
TestLoder
用來加載TestCase到TestSuite中
TextTestRunner
是來執行測試用例的
TextTestResult
保存測試結果的類
TestFixture
測試准備前和執行后要做到的工作
核心工作原理
unittest實例
准備待測方法
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
編寫測試方法
test_mathfunc.py
import unittest
from mathfunc import *
class TestMathFunc(unittest.TestCase):
#每個測試方法以test開頭
def test_add(self):
self.assertEqual(3,add(1,2))
self.assertNotEqual(3,add(2,2))
def test_minus(self):
self.assertEqual(1,minus(3,2))
def test_multi(self):
self.assertEqual(6,multi(2,3))
def test_divide(self):
self.assertEqual(2,divide(6,3))
self.assertEqual(2.5,divide(5,2))
if __name__ == '__main__':
#verbosity 輸出詳細程度 0 1 2
unittest.main(verbosity=2)
運行結果
測試通過
測試不通過
把除法/改為//(整除)報錯如下圖
TestSuite
上面的代碼運行無序,如果我們寫的用例有順序的話,就需要用TestSuite,被添加到TestSuite中的case會被按照順序執行。
編寫test_suite.py代碼如下
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")]
#addTests添加多個TestCase
#addTest添加單個TestCase
#suite.addTests(tests)
suite.addTests(unittest.TestLoader().loadTestsFromName('test_mathfunc.TestMathFunc'))
#suite.addTests(unittest.TestLoader().loadTestsFromNames(['test_mathfunc.TestMathFunc')]) 傳入列表
runner = unittest.TextTestRunner(verbosity=2)
runner.run(suite)
addTests方法
傳入一個TestCase對象的列表。
unittest.TestLoader().loadTestsFromName/Names
傳入一個TestCase對象,這個對象里可以包含多個test_開頭的方法,每個test_開頭的方法處理的時候都可以理解為一個TestCase實例。
TestFixture
在實際測試中,我們可能會遇到這種情況,需要測試的方法中有的需要連接數據庫,測試完畢需要還原數據,所以我們就需要一個准備環境的方法(setUp)還有清理環境的方法(TearDown),這就是TestFixture所包含的內容。
修改test_mathfunc.py如下
import unittest
from mathfunc import *
class TestMathFunc(unittest.TestCase):
#重寫了TestCase的方法
def setUp(self):
print("開始測試之前的環境搭建")
def tearDown(self):
print("環境清理")
def test_add(self):
self.assertEqual(3,add(1,2))
self.assertNotEqual(3,add(2,2))
def test_minus(self):
self.assertEqual(1,minus(3,2))
def test_multi(self):
self.assertEqual(6,multi(2,3))
#skip裝飾器
@unittest.skip("我不想執行除法")
#@unittest.skipIf(condition=,reason=) 當condition為true時跳過
#@unittest.skipUnless(condition=,reason=) 為false時跳過
def test_divide(self):
self.assertEqual(2,divide(6,3))
self.assertEqual(2.5,divide(5,2))
if __name__ == '__main__':
unittest.main(verbosity=2)
在實際測試中我們也可能會遇到這樣的情況,開始測試前需要連接數據庫,測試結束后關閉連接,不需要還原數據,只在開始和結束各自執行一次即可,setUpClass和tearDownClass的作用就是實現以上功能。
@classmethod
def setUpClass(cls):
print("開始測試之前的環境搭建統一")
@classmethod
def tearDownClass(cls):
print("最后清理環境")
輸出結果如下圖
沒有得到想要的結果,多次輸出發現setUp和tearDown輸出位置不定,猜想是因為不是單線程執行造成的,所以進行調試結果正確,暫存疑問。
跳過測試
有時候當某些條件的時候我們可能需要跳過測試,unittest也為我們提供了相應的方法
#@unittest.skipIf(condition=,reason=) 當condition為true時跳過
#@unittest.skipUnless(condition=,reason=) 為false時跳過
def test_divide(self):
self.assertEqual(2,divide(6,3))
self.assertEqual(2.5,divide(5,2))
執行結果如下
把結果保存到文件中
保存到文本文件中
with open('Unittest.txt','a') as f:
runner = unittest.TextTestRunner(stream=f, verbosity=2)
runner.run(suite)
會在項目目錄下生成Unittext.txt文本文件,內容如下
test_add (test_mathfunc.TestMathFunc) ... ok
test_divide (test_mathfunc.TestMathFunc) ... ok
test_minus (test_mathfunc.TestMathFunc) ... ok
test_multi (test_mathfunc.TestMathFunc) ... ok
----------------------------------------------------------------------
Ran 4 tests in 0.000s
OK
生成HTML
需要HTMLTsetRunner文件
with open('HTMLReport.html', 'wb') as f:
runner = HTMLTestRunner(stream=f, title="123", description="test", verbosity=2)
runner.run(suite)