原文網址:https://testing.googleblog.com/2014/10/testing-on-toilet-writing-descriptive.html
by Andrew Trenk
先來個問題:你要花多久時間來理解下面這個測試程式要做什麼?
1 2 3 4 5 6 7 8 9 10 |
@Test public void isUserLockedOut_invalidLogin() { authenticator.authenticate(username, invalidPassword); assertFalse(authenticator.isUserLockedOut(username)); authenticator.authenticate(username, invalidPassword); assertFalse(authenticator.isUserLockedOut(username)); authenticator.authenticate(username, invalidPassword); assertTrue(authenticator.isUserLockedOut(username)); } |
你大概閱讀了每一行程式 (說不定不只一次) 然後才理解每一行在做什麼。不過,如果一個測試有好的名子,你需要多少時間來理解下面這個測試想要做什麼呢?
1 |
isUserLockedOut_lockOutUserAfterThreeInvalidLoginAttempts |
透過良好的命名,你應該可以只透過閱讀測試程式的名稱,了解這個測試程式的想要測什麼,你甚至不用閱讀他的程式碼。前面提到的測試程式名稱只說明了他想要測試的情境 (scenario) 是 “invalidLogin”,但沒有真正的說明他期望的測試結果是什麼,所以必須要閱讀所有程式碼才能了解他的意圖。
將情境以及預期結果放在測試名稱還有其他的好處:
–
如果想要了解一個類別所有的可能的行為,只要閱讀他的測試類別 (Test class) 中的測試名稱就可,
相比於原本需要花費數分鐘甚至是數小時來閱讀測試程式甚至是該類別本身來理解其行為。這對於 code reviews 也是有幫助的,因為你可以快速的了解是不是測試都已經覆蓋到所有可能的 cases。
–
藉由給予測試更為顯式的名子,可以強迫你把一個測試許多不同行為的 testing 拆分為不同的測試。
不然,你可能會想要把針對不同行為來測試的斷言放在同一個測試程式內,時間一久,這會讓整個測試程式膨脹且變得難以理解與維護。
–
測試的行為不一定每次都能從程式碼中清楚的了解其精確行為。如果測試名稱沒有顯式的告知其精確行為,有時候你會需要猜測這個測試到底在做什麼。
–
你可以簡單的了解到還沒有涵蓋進測試的功能。如果你沒有看到測試名子有那個你想要看或測試的行為,那你就知道,這個測試還沒有被實作。
–
當一個測試失敗的時候,你可以立刻知道是什麼功能失效,而不用去看測試程式碼。
.
有許多的 common patterns 來維護一個 test 的名子 (一個方式是,用英文句子中 “should” 的方式來命名,e.g., shouldLockOutUserAfterThreeInvalidLoginAttempts
). 不論你用那種 pattern,同樣的建議依然適用:確保測試程式的名子包含了測試情境以及預期的結果 (Make sure test names contain both the scenario being tested and the expected outcome.)
不過,有時候只要清楚的標示出想這個 test 想要要測試的方法 (method) 就可以,特別是如果這個方法很簡單且只有跟他名子一樣好理解的單一功能。
Leave a Reply