最近在給一個客戶作技術諮詢,而後發現了客戶對於單元測試的一個有意思的現象。分享出來,你們一塊兒學習探討一下。html
這裏以java後端項目例,發現客戶寫的測試長下面的樣子。(代碼已經脫敏處理過。)java
@Autowired private SampleJob handler; @Test public void testStart() throws Exception { SampleParamVo paramVo = new SampleParamVo(); paramVo.setStartTime("2021-03-18"); paramVo.setEndTime("2021-03-18"); handler.execute(paramVo); }
@Autowired private SampleHandler handler; @Test public void testHandler() { handler.doHandler(new DateTime("2021-11-26"), null); }
那麼這樣的測試代碼有什麼問題呢?編程
@Autowired
這樣的代碼,增長了測試的耦合以及編寫成本。和客戶深聊了以後發現,原來客戶不一樣的人對單元測試的理解也不同。後端
因此咱們能夠發現,有的開發人員口中的單元測試其實應該屬於集成測試或者E2E測試,有的開發人員徹底沒有寫過單元測試,而測試人員理解單元測試是本身手動測試的時候用的測試用例。框架
那咱們就先來講說什麼是單元測試。ide
單元測試(unit testing),是指對軟件中的最小可測試單元進行檢查和驗證。
一般在java的世界裏面,單元測試就是指對一個public
的方法編寫檢查和驗證的代碼。函數
寫單元測試主要有兩大目的:微服務
當咱們寫完一個方法,咱們如何知道本身寫的方法是定期望工做的呢?這個時候就能夠添加單元測試來驗證咱們的代碼是定期望工做的。即當咱們給定指定的輸入,咱們得到指望的輸出,則咱們說這個功能是符合指望的。單元測試
其次,代碼不是寫了就永遠不變的,當需求變動時,新增需求時,修復bug時,都會修改代碼,而單元測試則能保護咱們已有的功能不被破壞。保護已有功能不會被本身破壞,被新人破壞,被新功能破壞。學習
下面是一個單元測試的例子
@Test public void should_return_fizz_given_input_can_be_divided_by_3() { FizzBuzz fizzBuzz = new FizzBuzz(); // Given String actual = fizzBuzz.sayIt(6); // When Assertions.assertEquals("Fizz", actual); // Then }
一個標準的單元測試包含如下幾個部分:
單元測試的Given、When、Then具體內容。
寫好單元測試要主要幾個要點:
單元測試一般須要覆蓋大量的case來保證咱們的代碼在絕大多數場景下都是定期望工做的。所以要作到這一點能夠參考下面兩大原則。這裏就不詳細講解這兩個原則,具體內容能夠Google。
單元測試有一個考覈的標準就是測試覆蓋率,指的是咱們的代碼有百分之多少被單元測試測到了。
說到單元測試,就不得不提測試金字塔,以下圖,最底層是單元測試,最頂層是UI測試。(測試金字塔有好幾種,但道理都是相通的)
看左邊的箭頭,越往下越快,越往上越慢,它主要包括編寫越快,運行越快,定位問題越快等。
看右邊的箭頭,越往下成本越低,越往上成本越高,包括時間成本,金錢成本,人員成本,維護成本等。
咱們在作單元測試的時候,經常可能訪問外部系統或者外部類,這些外部的不可控性會讓咱們的單元測試成本變得很高。
常見的外部不可控性有:HTTP訪問,增刪文件,隨機性,時間相關性,接口類等。
因而開發者便開始探索更廉價的方式來寫單元測試,mock就是其中的解決方案。
mock 對象運行在本地徹底可控環境內,利用 mock 對象模擬被依賴的資源,使開發者能夠輕易的建立一個穩定的測試環境。
mock是Test double理論中的一種,若是對test double理論感興趣,能夠到這裏瞭解更多,這裏就不展開說了。
仍是以java爲例,java的世界中經常使用的mock框架好比mockito。
下面是一個mock的例子。
@Test void should_return_100_when_get_list_size() { List map = mock(List.class); //當調用list.size()方法時候,返回100 when(map.size()).thenReturn(100); Assert.assertEquals(100, map.size()); }
單元測試是咱們測試的最小單位,所以咱們只測當前這個public
的方法中的實現,而方法中調用第三方類的東西,咱們都應該mock掉。
這樣的好處有兩個:
最後再昇華一下,簡單說一說TDD,TDD的全稱是Test driven development,即測試驅動開發。它是極限編程XP中的一個標準實踐。
TDD要求在編寫某個功能的代碼以前先編寫測試代碼,而後只編寫使測試經過的功能代碼,經過測試來推進整個開發的進行。
這樣作有四大好處:
這裏我就不詳細敘述TDD相關的話題了,由於TDD是一個比較大的話題,若是感興趣,下次專門開一個新話題來聊TDD。