一. unittest最核心的四個概念
unittest中最核心的四個概念是:test case,test suite,test runner,test fixturehtml
TestCase:一個testcase的實例就是一個測試用例:測試前準備環境的搭建(setUp),執行測試代碼(run),以及測試後環境的還原(tearDown)python
TestSuite:多個測試用例集合在一塊兒函數
TestLoader:是用來加載TestCase到TestSuite中的單元測試
TextTestRunner:用來執行測試用例的。其中的run(test)會執行TestSuite/TestCase中的run(result)方法測試
TextTestResult:保存TextTestRunner執行的測試結果ui
fixture:測試用例環境的搭建和銷燬(setUp/setUpClass,tearDown/tearDownClass)spa
二. unittest初級使用
1. 導入unittest模塊、被測文件或者其中的類code
2. 建立一個測試類,並繼承unittest.TestCaseorm
3. 重寫setUp和tearDown方法(若是有初始化條件和結束條件)htm
4. 定義測試函數,函數以test_開頭
5. 在函數體中使用斷言來判斷測試結果是否符合預期結果
6. 調用unittest.main()方法來運行測試用例
實例
1. 在工程下建立一個My_UnitTest的包,在這個包下面,建立一個被測對象myClass.py和一個測試用例Test_Myclass.py
2. 若是要測試數學中的加法和減法,測試對象myClass.py的內容爲
class Math: def add(self, a, b): return a + b def minus(self, a, b): return a - b
3. 在測試用例中引入unittest,被測文件中的類,注意測試用例是以test_開頭
import unittest from revise.My_UnitTest.myClass import Math class Test_MyClass(unittest.TestCase): def setUp(self): self.m = Math() def tearDown(self): pass def test_add(self): result = self.m.add(100, 23) self.assertEqual(123, result) #減法 def test_minus(self): result = self.m.minus(235, 111) self.assertEqual(124, result)
4. 測試用例的執行順序是以字母a-z和數字的從小到大的順序來排列的,因此上述兩個測試用例執行的順序是add在前,minus再後,能夠改改代碼驗證一下:
import unittest from revise.My_UnitTest.myClass import Math class Test_MyClass(unittest.TestCase): def setUp(self): self.m = Math() def tearDown(self): pass def test_add(self): result = self.m.add(100, 23) print("我先執行") self.assertEqual(123, result) #減法 def test_minus(self): result = self.m.minus(235, 111) print("我後執行") self.assertEqual(124, result)
運行結果:
Testing started at 12:36 ... D:\Program\python34\python.exe "D:\Program\PyCharm 2018.1.4\helpers\pycharm\_jb_unittest_runner.py" --path D:/python_workshop/python6/revise/My_UnitTest/Test_Myclass.py Launching unittests with arguments python -m unittest D:/python_workshop/python6/revise/My_UnitTest/Test_Myclass.py in D:\python_workshop\python6\revise\My_UnitTest 我先執行 我後執行 Ran 2 tests in 0.001s OK
若是但願minus先執行,add後執行,能夠給前者函數名加一個1,後者加一個2
def test_2_add(self): result = self.m.add(100, 23) print("我後執行") self.assertEqual(123, result) #減法 def test_1_minus(self): result = self.m.minus(235, 111) print("我先執行") self.assertEqual(124, result)
5. 若是在setUp裏實例化被測文件中的類,那麼每一條測試用例都要實例化一次被測類,用setUpClass()能夠只實例化一次,同理,tearDownClass也只作一次收尾工做
@classmethod def setUpClass(cls): cls.m = Math() @classmethod def tearDownClass(cls): pass
6. 用unittest.main()的方法來運行測試用例Test_Myclass.py
import unittest from revise.My_UnitTest.myClass import Math class Test_MyClass(unittest.TestCase): @classmethod def setUpClass(cls): cls.m = Math() @classmethod def tearDownClass(cls): pass def test_2_add(self): result = self.m.add(100, 23) print("我後執行") self.assertEqual(123, result) #減法 def test_1_minus(self): result = self.m.minus(235, 111) print("我先執行") self.assertEqual(124, result) if "__name__" == "__main__": unittest.main()
三. 斷言Assert
TestCase類提供了一系列的斷言,即結果比對的函數
Method |
Checks that |
New in |
assertEqual(a, b) |
a == b |
|
assertNotEqual(a, b) |
a != b |
|
assertTrue(x) |
bool(x) is True |
|
assertFalse(x) |
bool(x) is False |
|
assertIs(a, b) |
a is b |
3.1 |
assertIsNot(a, b) |
a is not b |
3.1 |
assertIsNone(x) |
x is None |
3.1 |
assertIsNotNone(x) |
x is not None |
3.1 |
assertIn(a, b) |
a in b |
3.1 |
assertNotIn(a, b) |
a not in b |
3.1 |
assertIsInstance(a, b) |
isinstance(a, b) |
3.2 |
assertNotIsInstance(a, b) |
not isinstance(a, b) |
3.2 |
四. unittest進階使用
方式一:類名("方法名")的集合
testsuite:
addTest() 添加一個測試用例
addTests([..]) 添加多個測試用例,addTests的參數是一個測試用例的集合
注意:addTests中執行用例的順序是按添加的前後順序進行的,若是這樣添加用例可能形成斷言失敗:
suite.addTests([TestFileOperate("test_00_read_all"),
TestFileOperate("test_01_write_data"),
TestFileOperate("test_03_read_all"),
TestFileOperate("test_02_add_data")])
正確的作法是:
suite.addTests([TestFileOperate("test_00_read_all"),
TestFileOperate("test_01_write_data"),
TestFileOperate("test_02_add_data"),
TestFileOperate("test_03_read_all")])
s = unittest.TestSuite()
s.addTest(testStudent("test_do_homework"))
runner = unittest.TextTestRunner()
runner.run(s)
實例1:addTest的使用
在My_UnitTest包下建立一個main.py
main.py中的代碼以下:
import unittest from revise.My_UnitTest.Test_Myclass import Test_MyClass #實例化測試套件對象 s = unittest.TestSuite() #調用addTest來加載測試用例——addTest(類名("用例函數名稱"))——添加一個測試用例 s.addTest(Test_MyClass("test_add")) s.addTest(Test_MyClass("test_minus")) #使用TextTestRunner來運行測試用例 #實例化 runner = unittest.TextTestRunner() #用run方法就是用來運行測試用例的 runner.run(s)
運行結果,控制檯輸出以下:
D:\Program\python34\python.exe D:/python_workshop/python6/revise/My_UnitTest/main.py .. ---------------------------------------------------------------------- Ran 2 tests in 0.001s OK
實例2:addTests的使用
import unittest from revise.My_UnitTest.Test_Myclass import Test_MyClass #實例化測試套件對象 s = unittest.TestSuite() #加載多個測試用例——參數爲列表——列表當中爲測試用例 s.addTests([Test_MyClass("test_add"), Test_MyClass("test_minus")])
#使用TextTestRunner來運行測試用例 #實例化 runner = unittest.TextTestRunner() #用run方法就是用來運行測試用例的 runner.run(s)
運行結果:
D:\Program\python34\python.exe D:/python_workshop/python6/revise/My_UnitTest/main.py .. ---------------------------------------------------------------------- Ran 2 tests in 0.000s OK
輸出測試報告-text-到文件
#建立一個文件,以寫的方式打開
fs = open("test_result.txt", "w")
runner = unittest.TextTestRunner(fs)
runner.run(s)
實例3:輸出測試報告到文件
import unittest from revise.My_UnitTest.Test_Myclass import Test_MyClass #實例化測試套件對象 s = unittest.TestSuite() #加載多個測試用例——參數爲列表——列表當中爲測試用例 s.addTests([Test_MyClass("test_add"), Test_MyClass("test_minus")]) #使用TextTestRunner來運行測試用例 #打開一個文件 fs = open("test_run_result.txt", "w") #實例化 runner = unittest.TextTestRunner(fs) #用run方法就是用來運行測試用例的 runner.run(s)
運行結果,控制檯沒有輸出,發現當前目錄下多了一個文本文件test_run_result.txt
控制檯輸出的信息寫到文本文件中了
方式二:unittest.TestLoader.discover方法匹配目錄下的用例
假如如今目錄下存在兩個測試用例,Test_Myclass.py和Test)_Myclass2.py,若是用addTests的方法添加用例到測試套件,未免有點麻煩,這時候須要使用TestLoader()這個類
代碼以下:
import unittest, os #實例化測試套件對象 s = unittest.TestSuite() #1.實例化TestLoader對象 2.使用discover去找到一個目錄下的全部測試用例 loader = unittest.TestLoader() #3.使用addTests將找到的測試用例放在測試套件下 s.addTests(loader.discover(os.getcwd()))
#運行 runner = unittest.TextTestRunner() runner.run(s)
運行結果:
.... ---------------------------------------------------------------------- Ran 4 tests in 0.000s OK
注意:源碼中discover方法, start_dir是要尋找的目錄路徑,pattern是查找條件,即在指定的目錄下查找以"test"開頭的測試用例(事實上,這個查找是不區分大小寫的,即Test開頭的也能找到)
方式三:unittest.TestLoader.loadTestsFromModule匹配模塊中的測試用例
ps:TetLoader類、TestSuite類須要先實例化再使用
五. 美化測試報告—html
python有提供第三方庫支持輸出的測試報告爲html樣式
庫名:HtmlTestRunner
導入:from HtmlTestRunnerNew import HTMLTestRunner
使用方式:
s = unittest.TestSuite()
s.addTests(測試用例)
fp = open(dir_config.htmlreport_dir + "/API_autoTest_{0}.html".format(curTime), "wb")
runner = HTMLTestRunnerNew.HTMLTestRunner(
stream = fp,
title = "QCD接口測試報告",
description = "QCD接口測試報告",
tester = "xiaozhai"
)
runner.run(s)
代碼修改以下:
import unittest, os, time from HTMLTestRunnerNew import HTMLTestRunner #實例化測試套件對象 s = unittest.TestSuite() #1.實例化TestLoader對象 2.使用discover去找到一個目錄下的全部測試用例 loader = unittest.TestLoader() #3.使用addTests將找到的測試用例放在測試套件下 s.addTests(loader.discover(os.getcwd())) #獲取當前時間 curTime = time.strftime("%Y-%m-%d_%H-%M-%S") #在當前目錄下建立一個html文件 fp = open(os.getcwd() + "/autoTest_report_{0}.html".format(curTime), "wb") #運行測試用例,生成測試報告 runner = HTMLTestRunner( stream=fp, title="單元測試報告", description="Math類的單元測試報告", tester="xiaozhai" ) runner.run(s)
運行效果:
D:\Program\python34\python.exe D:/python_workshop/python6/revise/My_UnitTest/main.py ok test_add (Test_Myclass.Test_MyClass) ok test_minus (Test_Myclass.Test_MyClass) ok test_add (Test_Myclass2.Test_MyClass2) ok test_minus (Test_Myclass2.Test_MyClass2) Time Elapsed: 0:00:00.001000 Sun Jul 8 18:17:18 2018 - Start Test:test_add (Test_Myclass.Test_MyClass) Sun Jul 8 18:17:18 2018 - Start Test:test_minus (Test_Myclass.Test_MyClass) Sun Jul 8 18:17:18 2018 - Start Test:test_add (Test_Myclass2.Test_MyClass2) Sun Jul 8 18:17:18 2018 - Start Test:test_minus (Test_Myclass2.Test_MyClass2)