軟體測試一般按階段劃分為:單元測試,集成測試,系統測試。單元測試(unit testing)是指對軟體中的最小可測試單元進行檢查和驗證。單元測試中單元的含義,單元就是人為規定的最小的被測功能模塊,如C語言中單元指一個函數,Java裡單元指一個類,圖形化的軟體中可以指一個窗口或一個菜單等。在實際項目中,單元測試往往由開發人員完成。
單元測試其實就是構造數據使用一段代碼去測試另一段代碼,理論上來說,不使用單元測試框架也能進行單元測試。但如果用於單元測試的代碼(即測試用例)增多,在沒有測試框架的情況下會變得擁擠、不可管理,這個時候引入測試框架就變得尤為重要。
單元測試框架提供了一種統一的編程模型,可以將測試定義為一些簡單的類,這些類中的方法可以調用希望測試的應用程式代碼。利用單元測試框架,可以很輕鬆地插入、設置和分解有關測試的功能,可以直觀方便地管理測試用例。
主流的單元測試框架,如Java的Junit、TestNg,python的Unittest、Pyunit、Pytest,通用的自動化測試框架Robot Framework等。
1)提供用例組織與執行
2)提供豐富的斷言方法
3)提供豐富的日誌與測試結果
Unittest是Python自帶的單元測試框架,不僅適用於單元測試,還可用於Web、Appium、接口自動化測試用例的開發與執行。該測試框架可組織執行測試用例,並且提供豐富的斷言方法,判斷測試用例是否通過,並最終生成測試結果。
Unittest官方文檔:https://docs.python.org/3/library/unittest.html
TestCase:即測試用例,Unittest提供testCase類來編寫測試用例,一個TestCase的實例就是一個測試用例。一條測試用例就是一個完整的測試流程,包括測試前準備環境的搭建(setUp),執行測試代碼(run),以及測試後環境的還原(tearDown),通過運行一條測試用例,可以對某一個問題進行驗證。
Fixture:即測試固件,用於測試用例環境的搭建和銷毀。在測試步驟執行前需要為該測試用例準備環境(SetUp),如啟動app或打開瀏覽器,測試步驟執行後需要恢復環境 (TearDown),如關閉app或瀏覽器,這時候就需要用到Fixture,使代碼更簡潔。
TestSuite:即測試套件,把需要執行的測試用例集合在一起就是TestSuite。使用TestLoader來加載TestCase到TestSuite中。
TextTestRunner:即測試執行器,用於執行測試用例。該模塊中提供run方法執行TestSuite中的測試用例,並返回測試用例的執行結果,如運行的用例總數、用例通過數、用例失敗數。
report:即測試報告。unittest框架沒有自帶的用於生成測試報告的模塊或接口,需要使用第三方的擴展模塊HTMLTestRunner。
斷言在自動化測試腳本中是很重要的內容,只有設置正確合適的斷言才能獲取正確的測試結果。Unittest框架提供了自己的斷言方法,如下:
注意:
如果斷言成功則該條測試用例通過,斷言失敗則該條測試用例執行失敗,且會拋出AssertionError錯誤。
以上提供的斷言方法中,都有一個msg參數,默認為None。如果msg參數有對應的值,則斷言失敗後該msg的值會作為失敗信息返回,如 assertEqual(a, b, msg="a與b不相等!") 。
測試對象:構造一個類Math,其中包含整數的加、減法運算。
calculator.py
class Math(): def __init__(self, a, b): self.a = int(a) self.b = int(b)
def sum(self): '''和''' return self.a + self.b
def sub(self): '''差''' return self.a - self.b測試需求:對Math類進行單元測試。接下來針對這個測試需求,使用unittest框架編寫測試用例。
項目目錄結構:後面的例子中,項目結構如下所示。
在Unittest框架下創建測試用例,步驟如下:
1)導入unittest模塊。
2)創建測試類。測試類的命名不做要求,但需要繼承unittest.TestCase類。
3)添加setUp()、tearDown()函數,即測試固件。當然還有setUpClass()、tearDownClass() 函數,區別後面會有介紹。
4)定義測試方法,即測試用例。測試方法名稱必須以test開頭,否則測試時該方法將不會被執行。測試方法裡需要添加斷言。
5)調試執行測試用例。執行當前模塊的測試用例時,調用unittest.main()方法,該方法會搜索該模塊下所有以test開頭的測試用例方法,並執行。其他方法後面介紹。
針對測試需求,編寫測試用例。目錄結構如下:
test_sum.py
import unittestfrom calculator import Math
class SumTest(unittest.TestCase): '''測試Math類中的sum函數''' def setUp(self): print("開始執行測試用例{}...".format(self))
def test_sum01(self): m = Math(3, 4) self.assertEqual(m.sum(), 7)
def test_sum02(self): m = Math(2, 8) self.assertEqual(m.sum(), 11)
def tearDown(self): print("測試用例{}執行結束...".format(self))
if __name__ == '__main__': unittest.main()運行結果:
.F======================================================================FAIL: test_sum02 (__main__.SumTest)Traceback (most recent call last): File "C:/Users/xiaoqq/Desktop/test_project/demo/testSum.py", line 15, in test_sum02 self.assertEqual(m.sum(), 11)AssertionError: 10 != 11
Ran 2 tests in 0.001s
FAILED (failures=1)開始執行測試用例test_sum01 (__main__.SumTest)...測試用例test_sum01 (__main__.SumTest)執行結束...開始執行測試用例test_sum02 (__main__.SumTest)...測試用例test_sum02 (__main__.SumTest)執行結束...
Process finished with exit code 0結果顯示:
1)test_sum01通過,test_sum02失敗。點"."表示通過,"F"表示失敗。
2)測試類中每個測試方法(即測試用例)執行前,都先執行setUp()方法,每個測試方法執行完畢後都要執行tearDown()方法。
3)斷言失敗會返回一個AssertionError。