cleanCode

無瑕的程式碼 - 單元測試

本文是《無瑕的程式碼》第九章 單元測試 的內容 稍微條列式筆記一下

本篇的程式碼來自於原書內容

寫單元測試的注意事項

讓測試整潔

測試程式跟產品程式一樣重要

測試的好處

單元測試給了我們擴充的彈性 為什麼呢 因為你不再害怕修改

測試的可讀性

何謂可讀呢 就是讀起來最順 來個例子 常見的assertTrue/assertFalse

@Test
public void turnOnLoTempAlarmAtThreashold() throws Exception {
  hw.setTemp(WAY_TOO_COLD); 
  controller.tic(); 
  assertTrue(hw.heaterState()); 
  assertTrue(hw.blowerState()); 
  assertFalse(hw.coolerState()); 
  assertFalse(hw.hiTempAlarm()); 
  assertTrue(hw.loTempAlarm());
}

這樣的程式有什麼問題嗎 當你在讀這份程式的時候 你的眼睛必須來回的左右移動

喔喔 heaterState 喔喔 希望是true

喔喔 blowerState 喔喔 希望是true

那要怎麼更好讀一點呢

AssertJ

我在領英做的一個project就是在unit test framework中引進AssertJ

用了之後 測試變這樣

@Test
public void turnOnLoTempAlarmAtThreashold() throws Exception {
  hw.setTemp(WAY_TOO_COLD); 
  controller.tic(); 
  assertThat(hw.heaterState()).isTrue(); 
  assertThat(hw.blowerState()).isTrue(); 
  assertThat(hw.coolerState()).isFalse(); 
  assertThat(hw.hiTempAlarm()).isFalse(); 
  assertThat(hw.loTempAlarm()).isTrue();
}

每行程式 眼睛都是只要掃過一次

每個測試程式越少assert越好

每個程式的斷言(assert) 越少越好 讓你每個程式專注的事情越少越好

FIRST

整潔的程式有一個法則F.I.R.S.T

F(Fast): 測試要夠快 他們要能夠快速地被運行 當測試跑起來太慢 你就不會想常常執行他們 不常執行就會比較晚發現問題 Iteration Speed就會低

I(Independent): 測試程式不該相互依賴 一個測試不應該成為下一個測試的設定條件 你要能獨立的運行各個測試 並且可以按照任何你想要的順序測試

R(Repeatable): 測試程式應該要可以在任何環境中重複執行 你可以在production測試 也可以在QA測試 在你搭火車回家沒網路時也要可以測試 當你的測試無論在什麼環境都可以執行的時候 你就會無法為測試沒過找藉口 因為只能是程式本身有錯

S(Self-Validating)(自我驗證): 測試程式應該輸出一個boolean 一看就該知道過 還是沒過 而不是需要人為的去看log 或是需要手動比較兩個檔案等等 這代表著一個測試程式的成敗取決於執行測試的人的主觀看法 測試應該絕對客觀 更不用說需要人為干預比較浪費時間

T(Timely)(及時): 寫測試程式要及時的寫 要恰好在正式程式寫完之前寫完(TDD的概念) 如果你在寫完正式程式之後才寫測試 那你可能會發現正式程式很難被測試