「你說我聽」 — Over Specification 一文後續之答客問

--

昨天 Kuma 貼出有關 Over Specification 的文章後,引來不少網友討論與轉發,還包含 TeDDDy 對於文中舉得不太好的例子的指教。我其實寫文章就是以記錄與交流為目的。有了讀者的指教,我就有機會更早發現原有觀念的問題,就有機會進步了。對此,我萬分感謝。

同時,有一位網友私訊了我一些問題。我同樣也是很感謝,因為有人問問題代表對作者的信任。我自當盡我所能來回答。我覺得這個問題,有因擾的應該不少,所以索性「來函照登」(因為是私訊,所以名字就碼掉)後,公開回答,以期能與更多同好交流。

來函照登

這位網友的第一個問題很好回答也很難回答。首先要看你的「API 功能測試」長什麼樣子。我先引用 Kent Beck 對 Unit Test 的看法。在 TDD 一書中, Kent Beck 認為 Unit Test 是一種「completely isolated from each other, creating their test fixtures from scratch each time」的測試。那你的「API 功能測試」有這種屬性嗎?如果有,那麼理當是一種 Unit Test。

我舉例:如果我的測試會在每個測項架一個臨時的 In-Memory DB,並且測完馬上 GC,那麼測試不論如何調換順序,彼此都互不影響,那這就可以視為一個 Unit Test。複充重要的(也是很常被誤會的)一點,一個 Unit 指的是一個「用戶可感受到的」功能,而不是一個 method,或是一個 Class。

問題二某種程度與上一段文末提到的觀念有關。一個接口如果是一個「會改變系統狀態的 Command」,它很有可能沒有回傳值。例如,在一個線上遊戲中,玩家可能會想改自己的暱稱。這時,我們就要提供一個 changeNickname 接口。這個接口不回傳東西也很合理,我就不是 Query 咩!

「你不 return value 我怎麼測?」

此時,這個問題就變成了:我們對「改暱稱」這個功能的描述,到底包含了幾個接口。什麼意思?正所謂不確定就舉例。你看看我們這麼描述如何:「用戶 kuma 把暱稱改成 andy 後,他的暱稱就變成了 andy。」好像合理,但什麼叫「變成了 andy」?好像還差一點對吧?那麼這樣如何:「用戶 kuma 把暱稱改成 andy 後,再查自己的暱稱,就得到了 andy 這個答案。」

是不是感覺問題二的答案呼之欲出了?

其實,接口沒有回傳值又如何?重點是這個 Command 把系統狀態改變了以後,系統的行為變成了什麼樣子。如果 Command 下了,系統狀態改變了,系統的行為卻沒有改變,那這個功能就不用做了。反正系統行為也不會改變,對吧?

所以,「改暱稱」的行為我們可以怎麼測?你可以試試這麼測:

  1. 創一個名為 kuma 的會員 1
  2. 把暱稱改成 andy
  3. 查會員 1 的資料,看看暱稱是不是 andy

這樣理應就不用開後門來驗狀態或驗互動了。

第三題嘛…我其實並不理解網友的問題。所以很抱歉我目前無法回答。如果這位網有願意補充更多 Context,那就太好了。

不過…其實是否是 Over Specification,的確也要看場景。如果分不出來,那我提供一個簡單的辨別方法:

你是否動了一點點東西,主要邏輯沒改,測試卻壞了?

如果有,那你有可能正在受 Over Specification 的危害。如果覺得困擾,就改了它吧!

Reference

  1. https://www.endoflineblog.com/unit-acceptance-or-functional-demystifying-the-test-types-part2

More about Me

--

--