看一線大廠測試人怎麼寫單元測試
我們都知道,開發軟體時,為程式碼編寫單元測試是很好的,但實際上,光有測試還不夠,好的測試的編寫同樣重要。
要做到這一點,考慮遵循一些固執的原則:
1、保持測試程式碼的緊湊和可讀性
要做到這一點,應該要進行毫不留情的重構,就像對生產程式碼應該做的那樣。否則讓測試程式碼隨著時間腐化,就是在測試裡面製造可怕的遺留程式碼。如果測試不能很容易重構,那麼生產程式碼也很難重構,從而導致生產系統的遺留程式碼。始終做一個勇敢的重構者。
2、避免編寫重複累贅的斷言
舉個例子,測試程式碼使用正則表示式生成內容,而這個正則表示式是跟生產程式碼的解析器中使用的一模一樣的。
一般來說,我們不希望在測試和程式碼之間複製邏輯。因此,在測試中複製正則表示式或其他內容不是一種選擇。在這種情況下,考慮測試輸入激勵/輸出結果之間的關係(f(輸入) - >輸出)可能會有幫助,例如,如果程式碼的目標是要做模板替換,不要在測試程式碼裡用原始值來做替換。相反,在測試裡面直接指定預期的計算結果。
// 使用
Assertions.assertThat(processTemplate("param1", "param2")).isEqualTo("this is 'param1', and this is 'param2'"));
// 而不要用
Assertions.assertThat(processTemplate("param1", "param2")).isEqualTo("this is '%s', and this is '%s'", param1, param2));
複製程式碼
3、覆蓋儘可能多的範圍,包括正面情況,甚至更重要的出錯程式碼路徑
通常,要做到這一點,最好的辦法試採用測試驅動開發(Test Driven Development)。通過TDD,人們可以在設計時識別可能會出錯的部分。不要羞於為一段小程式碼編寫一個簡單的測試用例。你永遠不知道什麼時候,為什麼以及以什麼方式,你會要用到甚至修改這段程式碼。
如果對軟體測試、介面測試、自動化測試、效能測試、LR指令碼開發、面試經驗感興趣可以175317069,群內會有不定期的發放免費的資料連結。如果你有好的學習資料可以私聊發我,我會註明出處之後分享給大家。
可以研究一下如何檢查測試的有效性,類似PIT這樣的工具可以進行變更測試,值得研究一下。
4. 不要Mock你不擁有的型別
這不是一個硬界限,但越過這條線很可能會產生反作用力!
TDD是關於設計的,也是關於測試的,兩者一樣重要,在模擬外部API時,測試不能用於驅動設計,API屬於第三方;這個第三方可以,並且實際上也經常會更改API的簽名和行為。
想象一下Mock第三方Lib的程式碼。在第三方庫的某次升級之後,它的邏輯可能會改變,但測試套件仍會執行得很好,因為它被Mock了。所以後來,你認為一切都很好,畢竟構建牆是綠色的,軟體部署上去,然後......嘣
如果你感覺需要Mock第三方庫,可能表明你當前的設計與第三方庫沒有足夠的分離。
另一個問題是第三方庫可能很複雜,需要大量的Mock才能正常工作。這導致過度指定的測試和複雜的測試輔助裝置,這本身就損害了緊湊和可讀的目標。或者由於模擬外部系統過於複雜,從而導致測試程式碼對生產程式碼的覆蓋不足。
取而代之的最常見的方法,是圍繞外部lib / 系統建立包裝器,儘管應該意識到抽象洩漏的風險,其中過多的低階API,概念或異常超出了包裝器的邊界。為了驗證與第三方庫的整合,編寫整合測試,並使它們儘可能緊湊和可讀。
5、不要Mock一切,這是一種反模式
如果一切都被Mock,我們真的在測試生產程式碼嗎?該不Mock的時候,不要猶豫!
不要Mock值物件
為什麼人們甚至想要這樣做?
因為例項化物件太痛苦了! => 不是正當理由。
如果建立新的物件太難了,那麼程式碼可能需要一些嚴肅的重構。另一種方法是為您的值物件建立構建器 - 有一些工具,包括IDE外掛,Lombok和其他。還可以在測試類路徑中建立有意義的工廠方法。
abstract class CustomerCreations {
public static Customer customer_with_a_single_item_in_the_basket() {
// long init sequence
}
}
複製程式碼
Mockito專注於物件之間的相互操作,這是面向物件程式設計的核心部分。