2017年6月20日 星期二

Python Tutorial 第六堂(1)使用 unittest 單元測試

Source From Here
Preface
unittest 有時亦稱為 “PyUnit",是 JUnit 的 Python 語言實現,JUnit 是個單元測試(Unit test)框架,單元測試指的是測試一個工作單元(a unit of work)的行為。舉例來說,對於建築橋墩而言,一個螺絲釘、一根鋼筋、一條鋼索甚至一公斤的水泥等,都可謂是一個工作單元,驗證這些工作單元行為或功能 (硬度、張力等)是否符合預期,方可確保最後橋墩安全無虞。

測試一個單元,基本上要與其它的單元獨立,否則你會在同時測試兩個單元的正確性,或是兩個單元之間的合作行為。就軟體測試而言,單元測試通常指的是測試某個函式(或方法),你給予該函式某些輸入,預期該函式會產生某種輸出,例如傳回預期的值、產生預期的檔案、新增預期的資料等。unittest 模組主要包括四個部份:
* 測試案例Test case)測試的最小單元。
* 測試設備Test fixture)執行一或多個測試前必要的預備資源,以及相關的清除資源動作。
* 測試套件Test suite)一組測試案例、測試套件或者是兩者的組合。
* 測試執行器Test runner)負責執行測試並提供測試結果的元件。

測試案例
對於測試案例的撰寫,unittest 模組提供了一個基礎類別 TestCase,你可以繼承它來建立新的測試案例。例如:
  1. import unittest  
  2. import calculator  
  3.   
  4. class CalculatorTestCase(unittest.TestCase):  
  5.     def setUp(self):  
  6.         self.args = (32)  
  7.   
  8.     def tearDown(self):  
  9.         self.args = None  
  10.   
  11.     def test_plus(self):  
  12.         expected = 5;  
  13.         result = calculator.plus(*self.args);  
  14.         self.assertEquals(expected, result);  
  15.   
  16.     def test_minus(self):  
  17.         expected = 1;  
  18.         result = calculator.minus(*self.args);  
  19.         self.assertEquals(expected, result);  
每個測試必須定義在一個 test 名稱為開頭的方法中,一個 TestCase 的子類別,通常用來為某個類別或模組的單元方法或函式定義測試。

測試設備
許多單元測試經常藬用相同的測試設備,你可以在 TestCase 的子類別中定義 setUp 與 tearDown 方法,測試執行器會在每個測試運行之前執行 setUp 方法,每個測試運行之後執行 tearDown 方法。一個實際情境可以像是在 setUp 方法中建立新表格並在表格中新增資料,執行測試之後,在 tearDown 方法中刪除表格。

測試套件
根據測試的需求不同,你可能會想要將不同的測試組合在一起,例如,CalculatorTestCase 中可能有數個 test_xxx 方法,而你只想將 test_plus 與 test_minus 組裝為一個測試套件的話,可以如下:
  1. suite = unittest.TestSuite()  
  2. suite.addTest(CalculatorTestCase('test_plus'))  
  3. suite.addTest(CalculatorTestCase('test_minus'))  
或者是使用一個 list 來定義要組裝的 test_xxx 方法清單:
  1. tests = ['test_plus''test_minus']  
  2. suite = unittest.TestSuite(map(CalculatorTestCase, tests))  
如果想要自動載入某個 TestCase 子類別中所有 test_xxx 方法,可以如下:
  1. unittest.TestLoader().loadTestsFromTestCase(CalculatorTestCase)  
你可以任意組合測試,例如,將某個測試套件與某個 TestCase 中的 test_xxx 方法組合為另一個測試套件:
  1. suite2 = unittest.TestSuite()  
  2. suite2.addTest(suite)  
  3. suite2.addTest(OtherTestCase('test_orz'))  
也可以將許多測試套件再全部組合為另一個測試套件:
  1. suite1 = module1.TheTestSuite()  
  2. suite2 = module2.TheTestSuite()  
  3. alltests = unittest.TestSuite([suite1, suite2])  
測試執行器
你可以在程式碼中直接使用 TextTestRunner,例如:
  1. suite = (unittest.TestLoader()  
  2.                  .loadTestsFromTestCase(CalculatorTestCase))  
  3. unittest.TextTestRunner(verbosity=2).run(suite)  
或者是透過 unittest.main 函式來執行:
  1. unittest.main(verbosity=2)  
一個執行的畫面如下:

如果不想透過程式碼定義,也可以在命令列中使用 unittest 模組來運行模組、類別或甚至個別的測試方法:
# python -m unittest test_module1 test_module2
# python -m unittest test_module.TestClass
# python -m unittest test_module.TestClass.test_method

如果想得到更詳細的測試資訊,可以加上 -v 引數:
# python -m unittest test_unit
..
----------------------------------------------------------------------
Ran 2 tests in 0.000s

OK
[root@l2server Tmp]# python -m unittest -v test_unit
test_minus (test_unit.CalculatorTestCase) ... ok
test_plus (test_unit.CalculatorTestCase) ... ok

----------------------------------------------------------------------
Ran 2 tests in 0.000s

OK

想得知 unittest 所有可用的引數,可以使用以下指令:
# python -m unittest -h


沒有留言:

張貼留言

[Git 常見問題] error: The following untracked working tree files would be overwritten by merge

  Source From  Here 方案1: // x -----删除忽略文件已经对 git 来说不识别的文件 // d -----删除未被添加到 git 的路径中的文件 // f -----强制运行 #   git clean -d -fx 方案2: 今天在服务器上  gi...