8

你就是寫太多測試才會沒時間(1):證明自己的清白

 1 year ago
source link: https://teddy-chen-tw.blogspot.com/2023/06/1.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

你就是寫太多測試才會沒時間(1):證明自己的清白

June 17 16:31~18:24

截圖 2023-06-17 下午4.26.45

▲圖1:單元測試驗證修改過的email是否正確

前言

Teddy的朋友Kuma幾個月前寫了一本書:《你就是不寫測試才會沒時間:Kuma 的單元測試實戰 -- Java篇》。的確,自從Teddy在N年前開始寫第一個自動化單元測試之後,Teddy一直認為測試是開發不可分割的一部分。好的測試可以協助釐清規格、作為驗收條件、找出回歸錯誤,以及支持重構,讓開發人員走得更穩、更快。

但是,隨著測試案例越來越多,管理與重構這些測試案例就變成另一個頭痛的問題。下周二Teddy舉辦一個網路演講,講題是:「你就是寫太多測試才會沒時間」,就是要討論應對這種現象的方法。這個講題這雖然是一句帶有玩笑性質的話,但也代表對於測試看法的一種演進過程:

不寫測試沒時間 ---> 寫了測試有時間--->  累積太多欠管理的測試又變得沒時間 ---> 下階段是什麼?

針對這個主題,今天談一個單純一點的情況:如何簡單驗證待測程式沒有做它不該做的事情?

從範例看問題

軟體測試有一個基本原則:「除了要驗證待測程式做了該做的事情,也要驗證它沒有做不該做的事。」舉個例子,圖1中的User物件,呼叫它的changeEmail方法設定新的email,在第101行中驗證email是否被正確設定。這種測試很常見,但嚴格講起來這個測試並不完整。除了驗證email有被正確修改以外,還需要確保User物件的其他欄位沒有被改變。因為難保changeEmail的實作,除了改變email以外,會不會不小心動到User物件的其他欄位,例如把nickname清空。

但是,如果每一個測試案例都去驗證不應該被改動的欄位真的沒有被異動,將會增加很多測試工作,如圖2所示。

截圖 2023-06-17 下午6.02.24

▲圖2:第104~109行驗證User除了email以外的其他欄位維持原狀

這還只是單元測試而已,如果是Use Case層次的測試案例,例如ChangeEmailUseCase,從Repository讀出User之後,理論上相同的assertion還要再寫一次。除了需要花費而外時間撰寫測試,也造成duplication code,增加日後維護測試案例的成本。

解決方案

先講結論,Teddy使用AssertJ這個「Fluent assertions for java」的測試工具來解決這個問題。圖3為Teddy使用ezSpec(Teddy自行開發的BDD工具軟體,可以直接用Java寫Given-When-Then,過一陣子會開源)所撰寫的ChangeEmailUseCase測試,第73行透過Repository從資料庫中拿出修改過email的User物件,然後第74行比對email欄位是否被正確修改。

接著在第76~78行使用AspectJ的assertThat做為比對物件的方式,呼叫usingRecursiveComparison,然後透過ignoringFieldsMatchingRegexes指定那些欄位不需要比對,最後再呼叫isEqualTo,就可以排除特定欄位之後,比對兩個物件是否相等。

圖3的程式範例擷取自ezKanban,由於ezKanban支援樂觀鎖,因此在每一個Aggregate物件身上都有一個version欄位用以作為樂觀鎖使用。因為User物件是一個Aggregate,所以User的email改變之後,version數值加1,因此在第77行比對修改前與修改後的兩個User物件實例是否相等的時候,除了排除email,也要排除version。

截圖 2023-06-17 下午3.56.51

▲圖3:採用ezSpec撰寫的ChangeEmailUseCase測試

結論

透過工具幫忙,就可以用很簡潔的方式去確保物件的狀態。雖然Teddy在範例中使用AssertJ做為比對的工具,但相信不同的語言應該可以找到類似的工具。如果真的找不到怎麼辦?那就自己寫一個啊。

友藏內心獨白:開發人員就是要有Maker精神。


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK