2012年3月25日 星期日

失敗的單元測試



我一向習慣用 TDD 來寫程式, 也很自豪寫出的程式品質還不賴, 尤其是用TDD開發完成後一定會順便產出一堆 unit test, 我以為若是有另一位開發者中途加入, 他一定很容易看懂我的程式, 既有的 unit test 也能幫助他確認沒有把程式改壞, 上手負擔會比較輕. 但是最近新進弟兄賴瑞的遭遇, 讓我知道我錯了...

賴瑞修改程式, 改變了某個 class 後 unit test 就無法通過了. 這是預期中的結果, 因為 unit test 也要跟著改變才會符合最新的 class 行為. 賴瑞很讚, 不囉嗦馬上就去改我寫的 unit test. 但也馬上遇到問題了, unit test 的 code 實在太難懂了, 他花一天把程式改完, 卻花了兩天修改 unit test...

我原以為是好東西的 unit test 卻變成賴瑞的絆腳石... 這這這..這到底是怎麼一回事?

賴瑞: "單元測試不夠單元"

一個好的 unit test 應該是自成一體, 簡單幾個步驟設定, 驗證一個結果. 但以我寫出的某個 unit test 為例, 要先設定 http server 依序傳回四個回應, 又要設定 mongo db 裡面的兩個 collection 要含有某 document, 驗證的東西又複雜無比, 難怪賴瑞看到眼睛痛.

這是 unit test 的寫得不好嗎? 是, 而且主體程式寫得也糟, 反應在 unit test 上就是這個樣子. 如果我的主體程式沒有直接 用 HttpRequest class 跟 http server 溝通, 而是透過某個 remote interface 跟 http server 要資料, 那 unit test 中就可以用 mock object 來代替 http server, 同理也可套用到 mongo db 上. 若是我好好遵照這個原則, unit test 一定簡單易讀易改多了, 每個 test 少個 30行程式碼吧.

unit test 的程式碼也是程式碼

希望 unit test 也易讀易懂易維護, 那對待 unit test 程式碼也要像一般的程式碼一樣. 寫一般程式的時候, 只要 copy & paste 程式碼, 腦中警鈴就會響起 -

有重複的程式碼, 這是萬惡根源, 等等要 refactor!

但copy & paste unit test 時, 這警鈴卻昏迷了, 於是我的 unit test 越來越可怕...

我寫一般程式的時候, function 命名都還蠻計較的, 會儘量想個名實相符的東西. 在命名 test function 時我卻滿偷懶的, 有時會寫出這樣的 function 名 - testUploadHandler2..... (烏鴉飛)

My bad may bad my bad .....

武器越大隻, 後座力也越大

TDD 的愛用者, 若你也跟我一樣會偷懶不把 dependency 用 interface 區隔, 不注意 unit test 程式碼的品質, 那別人修改你的程式的時候會遇到更大的困難, 因為除了程式碼難改, unit test 更難改. 慎之 慎之

2011年9月23日 星期五

我的TDD經驗(1)

從T社換到I社之後,一直在一個三人團隊做研究計畫。我們三個很早就說好儘量互相協助,包含寫程式也一起 pair programming,並利用test driven development(TDD)。我一直以來都是用TDD,另外兩位同事只是久聞TDD之名,不曾見過其人,所以當我使用各種技巧(讓本以為無法測試的程式變得可以測試、從很簡單的小功能寫成完整功能、...)寫出程式的時候,同事臉上隱約出現不可置信+恍然大悟的表情。

話說TDD我也是有一段漫長的自學過程...

2011年8月29日 星期一

ASUS WL530g 狂掉封包

ASUS 無線AP WL530g 是個老產品了,之前封存了好多年,最近才又拿出來用。果然,一用就讓我回憶起當初為何要封存它了。

2011年8月3日 星期三

Linux kernel coding style (下)

13. 列印 kernel 訊息

kernel開發者喜歡被大家看成是個受過教育的人,所以字要拼對,才能製造這種好印象。不要用一些跛腳的字眼,像是"dont",要用"do not" 或是 "don't"。訊息文字要扼要 清楚 精確。

kernel訊息文字結尾不需要句點。

列印數字的時候加上括號(%d)是毫無意義的,應該避免。

在linux/device.h中有專為driver提供的巨集,可以方便的印出適合訊息文字,如dev_err() dev_warn() dev_info()。要印出與driver無關的訊息,可以用linux/printk.h中的pr_debug()或是pr_info()。


2011年8月1日 星期一

幼稚園的畢業生感言

今天我才知道,大部分幼稚園的畢業生感言是用英文說的。當然,我說的是台灣台北的幼稚園,不是美國紐約的幼稚園。

2011年7月28日 星期四

Linux kernel coding style (中)

7. 從單一出口離開function


雖然有些人打死不用goto,但在kernel裡goto還是很好用的,尤其是goto到function最後統一處理些資源回收的工作。另外:

  • 無條件執行的statement容易理解
  • 減少nesting
  • 很容易新增exit point,減少錯誤的機會
  • 幫助compiler作些最佳化處理

2011年7月26日 星期二

Linux kernel coding style (上)

小弟最近為了這個新硬體,加了一個linux kernel module並改寫了arch/powerpc下的一些code,嘗試要把修改的code送回公司的repo裡。結果寫得太差,光是coding stlye的因素就被maintainer修改了快超過500行,沒有被maintainer直接踢回來是他心地善良。於是我花了點時間看 linux coding style 的文件,並把重點摘要於此,希望能讓初次踏入linux kernel裡的人很快了解這個最最最基本的東西。