
測試執行緒應用程式
在本章中,我們將學習關於執行緒應用程式測試的內容。我們還將學習測試的重要性。
為什麼要測試?
在我們深入討論測試的重要性之前,我們需要了解什麼是測試。一般來說,測試是一種找出某件事工作情況有多好的技術。另一方面,具體來說,如果我們談論計算機程式或軟體,那麼測試就是訪問軟體程式功能的技術。
在本節中,我們將討論軟體測試的重要性。在軟體開發中,在將軟體釋出給客戶之前必須進行二次檢查。這就是為什麼由經驗豐富的測試團隊測試軟體非常重要的原因。請考慮以下幾點,以瞭解軟體測試的重要性:
提高軟體質量
當然,沒有公司希望交付低質量的軟體,也沒有客戶希望購買低質量的軟體。測試透過查詢和修復其中的錯誤來提高軟體質量。
客戶滿意度
任何業務中最重要的部分是客戶的滿意度。透過提供無錯誤且高質量的軟體,公司可以實現客戶滿意度。
減少新功能的影響
假設我們製作了一個 10000 行的軟體系統,我們需要新增一個新功能,那麼開發團隊會擔心此新功能對整個軟體的影響。這裡,測試也起著至關重要的作用,因為如果測試團隊製作了一套良好的測試,那麼它可以使我們免受任何潛在的災難性故障。
使用者體驗
任何業務的另一個最重要的部分是該產品使用者的體驗。只有測試才能確保終端使用者發現該產品簡單易用。
降低成本
測試可以透過在軟體開發的測試階段查詢和修復錯誤來降低軟體的總成本,而不是在交付後修復它。如果在軟體交付後出現重大錯誤,則會增加其有形成本(例如,支出方面)和無形成本(例如,客戶不滿、公司負面聲譽等)。
測試什麼?
始終建議對要測試的內容有適當的瞭解。在本節中,我們首先將瞭解在測試任何軟體時測試人員的主要動機。在測試時,應避免程式碼覆蓋率,即我們的測試套件命中多少行程式碼。這是因為,在測試時,僅關注程式碼行數不會為我們的系統增加任何實際價值。即使在部署後,也可能存在一些錯誤,這些錯誤會在稍後階段反映出來。
考慮以下與要測試的內容相關的要點:
我們需要專注於測試程式碼的功能,而不是程式碼覆蓋率。
我們需要首先測試程式碼中最重要的部分,然後轉向程式碼中不太重要的部分。這肯定會節省時間。
測試人員必須擁有多種不同的測試,可以將軟體推到其極限。
測試併發軟體程式的方法
由於能夠利用多核架構的真正能力,併發軟體系統正在取代順序系統。近年來,併發系統程式已用於從手機到洗衣機、從汽車到飛機等各種事物中。我們需要更加小心地測試併發軟體程式,因為如果我們在已經存在錯誤的單執行緒應用程式中添加了多個執行緒,那麼我們最終將得到多個錯誤。
併發軟體程式的測試技術主要集中在選擇能夠暴露潛在有害模式(如競爭條件、死鎖和原子性違規)的交錯。以下是兩種測試併發軟體程式的方法:
系統探索
這種方法旨在儘可能廣泛地探索交錯的空間。此類方法可以採用蠻力技術,其他方法採用部分順序減少技術或啟發式技術來探索交錯的空間。
屬性驅動
屬性驅動方法依賴於以下觀察結果:併發故障更有可能在暴露特定屬性(例如可疑記憶體訪問模式)的交錯下發生。不同的屬性驅動方法針對不同的故障,如競爭條件、死鎖和原子性違規,這進一步取決於一個或另一個特定屬性。
測試策略
測試策略也稱為測試方法。該策略定義瞭如何進行測試。測試方法有兩種技術:
主動
一種在構建建立之前儘早啟動測試設計過程以查詢和修復缺陷的方法。
被動
一種在開發過程完成後才開始測試的方法。
在對 Python 程式應用任何測試策略或方法之前,我們必須對軟體程式可能存在的錯誤型別有一個基本的瞭解。錯誤如下:
語法錯誤
在程式開發過程中,可能會出現許多小錯誤。這些錯誤大多是由於打字錯誤造成的。例如,缺少冒號或關鍵字拼寫錯誤等。此類錯誤是由於程式語法錯誤而不是邏輯錯誤造成的。因此,這些錯誤稱為語法錯誤。
語義錯誤
語義錯誤也稱為邏輯錯誤。如果軟體程式中存在邏輯或語義錯誤,則該語句將正確編譯和執行,但不會給出所需的輸出,因為邏輯不正確。
單元測試
這是測試 Python 程式最常用的測試策略之一。此策略用於測試程式碼的單元或元件。透過單元或元件,我們的意思是程式碼的類或函式。單元測試透過測試“小”單元來簡化大型程式設計系統的測試。藉助上述概念,單元測試可以定義為一種方法,其中測試單個原始碼單元以確定它們是否返回所需的輸出。
在我們後續的部分中,我們將學習關於單元測試的不同 Python 模組。
unittest 模組
第一個用於單元測試的模組是 unittest 模組。它受到 JUnit 的啟發,並且預設包含在 Python3.6 中。它支援測試自動化、共享測試的設定和拆卸程式碼、將測試聚合到集合中以及測試與報告框架的獨立性。
以下是 unittest 模組支援的一些重要概念
測試夾具
它用於設定測試,以便在開始測試之前執行它,並在測試完成後拆除。它可能涉及在開始測試之前建立臨時資料庫、目錄等。
測試用例
測試用例檢查從特定輸入集中是否獲得了所需的響應。unittest 模組包含一個名為 TestCase 的基類,可用於建立新的測試用例。它預設包含兩個方法:
setUp() - 在執行測試夾具之前設定測試夾具的鉤子方法。這在呼叫已實現的測試方法之前呼叫。
tearDown( - 在執行類中所有測試後解構類夾具的鉤子方法。
測試套件
它是測試套件、測試用例或兩者的集合。
測試執行器
它控制測試用例或套件的執行,並將結果提供給使用者。它可以使用 GUI 或簡單的文字介面來提供結果。
示例
以下 Python 程式使用 unittest 模組來測試名為 Fibonacci 的模組。該程式有助於計算數字的斐波那契數列。在此示例中,我們建立了一個名為 Fibo_test 的類,以透過使用不同的方法來定義測試用例。這些方法繼承自 unittest.TestCase。我們使用兩個預設方法 - setUp() 和 tearDown()。我們還定義了 testfibocal 方法。測試的名稱必須以字母 test 開頭。在最後一個塊中,unittest.main() 為測試指令碼提供了一個命令列介面。
import unittest def fibonacci(n): a, b = 0, 1 for i in range(n): a, b = b, a + b return a class Fibo_Test(unittest.TestCase): def setUp(self): print("This is run before our tests would be executed") def tearDown(self): print("This is run after the completion of execution of our tests") def testfibocal(self): self.assertEqual(fib(0), 0) self.assertEqual(fib(1), 1) self.assertEqual(fib(5), 5) self.assertEqual(fib(10), 55) self.assertEqual(fib(20), 6765) if __name__ == "__main__": unittest.main()
從命令列執行時,上述指令碼產生的輸出如下所示:
輸出
This runs before our tests would be executed. This runs after the completion of execution of our tests. . ---------------------------------------------------------------------- Ran 1 test in 0.006s OK
現在,為了更清楚起見,我們正在更改幫助定義斐波那契模組的程式碼。
以下程式碼塊為例:
def fibonacci(n): a, b = 0, 1 for i in range(n): a, b = b, a + b return a
對程式碼塊進行了一些更改,如下所示:
def fibonacci(n): a, b = 1, 1 for i in range(n): a, b = b, a + b return a
現在,在使用更改後的程式碼執行指令碼後,我們將獲得以下輸出:
This runs before our tests would be executed. This runs after the completion of execution of our tests. F ====================================================================== FAIL: testCalculation (__main__.Fibo_Test) ---------------------------------------------------------------------- Traceback (most recent call last): File "unitg.py", line 15, in testCalculation self.assertEqual(fib(0), 0) AssertionError: 1 != 0 ---------------------------------------------------------------------- Ran 1 test in 0.007s FAILED (failures = 1)
上述輸出表明該模組未能給出所需的輸出。
Docktest 模組
docktest 模組也有助於單元測試。它也預先打包在 python 中。它比 unittest 模組更容易使用。unittest 模組更適合複雜的測試。要使用 doctest 模組,我們需要匯入它。相應函式的文件字串必須具有互動式 python 會話及其輸出。
如果我們的程式碼一切正常,那麼 doctest 模組將不會有任何輸出;否則,它將提供輸出。
示例
以下 Python 示例使用 docktest 模組來測試名為 Fibonacci 的模組,該模組有助於計算數字的斐波那契數列。
import doctest def fibonacci(n): """ Calculates the Fibonacci number >>> fibonacci(0) 0 >>> fibonacci(1) 1 >>> fibonacci(10) 55 >>> fibonacci(20) 6765 >>> """ a, b = 1, 1 for i in range(n): a, b = b, a + b return a if __name__ == "__main__": doctest.testmod()
我們可以看到,名為 fib 的相應函式的文件字串具有互動式 python 會話及其輸出。如果我們的程式碼正常,則 doctest 模組將不會有任何輸出。但為了檢視它的工作原理,我們可以使用 –v 選項執行它。
(base) D:\ProgramData>python dock_test.py -v Trying: fibonacci(0) Expecting: 0 ok Trying: fibonacci(1) Expecting: 1 ok Trying: fibonacci(10) Expecting: 55 ok Trying: fibonacci(20) Expecting: 6765 ok 1 items had no tests: __main__ 1 items passed all tests: 4 tests in __main__.fibonacci 4 tests in 2 items. 4 passed and 0 failed. Test passed.
現在,我們將更改幫助定義斐波那契模組的程式碼
以下程式碼塊為例:
def fibonacci(n): a, b = 0, 1 for i in range(n): a, b = b, a + b return a
以下程式碼塊有助於進行更改。
def fibonacci(n): a, b = 1, 1 for i in range(n): a, b = b, a + b return a
即使在沒有使用 –v 選項的情況下執行指令碼,使用修改後的程式碼,我們也會得到如下所示的輸出。
輸出
(base) D:\ProgramData>python dock_test.py ********************************************************************** File "unitg.py", line 6, in __main__.fibonacci Failed example: fibonacci(0) Expected: 0 Got: 1 ********************************************************************** File "unitg.py", line 10, in __main__.fibonacci Failed example: fibonacci(10) Expected: 55 Got: 89 ********************************************************************** File "unitg.py", line 12, in __main__.fibonacci Failed example: fibonacci(20) Expected: 6765 Got: 10946 ********************************************************************** 1 items had failures: 3 of 4 in __main__.fibonacci ***Test Failed*** 3 failures.
在上面的輸出中我們可以看到,有三個測試失敗了。