Re: [討論] Unit test 的撰寫請益
※ 引述《shane87123 (陽光大肥宅)》之銘言:
: 先說我對 Unit test 的看法:測試單元(可能是 function)的邏輯是否正確
: 好,進入正題
: 小弟最近剛工作,稍微讀了一下負責的 project 的程式碼後,
: 要開始開發 Unit test。
: 現況是,各個 file (.c) dependency 很重,
: 常常會有一份 code 內其實呼叫了很多別份 code 的 function,
: 舉例來說
: A() {
: B();
: C();
: if (check)
: D();
: }
: 族繁不及備載,
: 而我目前設計有兩個方向,
: 1.
: 將 B() C() D() 全部 fake ,單純去測試 A() 的邏輯是否正確
: 這樣做感覺上會比較單純,一個 test case 只去 test A(),
: 而且不需要去 include B() C() D() 的 header,
: 這樣一來 build 起來也比較容易,因為 include 那些 header 又會 dependency 到其他檔
: 情況會非常複雜
: 缺點是 coverage 比較差,B() C() D()要額外去寫 test case
先說結論,先都不要寫。
Legacy system 要先補大範圍的 integration test,確定整體的行為是對的。
如果 code 沒有要再改,不用補細部 unit tests。
原因是因為,原本 API 可能因為設計不良,導致無法寫 unit test
得先 refactor 才有辦法讓它變成 testable,這情況就要先 refactor 再補 UT
而 integration test 會一定程度減少 refactor 造成 regression bugs。
再來正名運動一下,fake/mock/stub 都是 test double,但用途不一樣
https://martinfowler.com/articles/mocksArentStubs.html
fake 仍然是一個大致完整的實作,只是比較簡化。
例如本來是 on-disk 的 key-value database,fake 就可以用 in-memory 的一個
dictionary 物件換掉,簡化許多但是 API 有提供 "一樣的行為 (key 的讀寫)"
stub 則是多半只會 return 固定的 constant,本身沒實作行為
用 test double 主要好處是減少 dependency,然後測試速度會快。
測試大規模系統,如果讀寫檔案,讀寫資料庫都是真的去讀,那就牽扯到跨系統整合
會花超多時間跑,也比較是 integration test
Unit test 的目標要能快速給予回饋,所以很強調執行速度。用 test double 換掉
同時能提升 isolation,也避免一些意外狀況造成測試失敗。
例如程式邏輯明明沒錯,卻因為外部因素而失敗跑不過,
所以 unit test 的書上多推廣用 test double。
但實務上,持續維護 test double 和真實物件的行為一致,是一件高成本而且困難的事如果你改變了真實物件的行為,所有有用 test double 的地方都要重新改寫
而且 fake 物件實作有是可能會錯,那反而會製造更多問題
所以 To fake or not to fake? That is the question.
後來有些書上就提倡 prefer real object,能用真的就盡量不要用假的。
根據專案的狀況,你可以選擇最適合的方式,沒有絕對正確答案
然後目標不是高 coverage。目標是最 business critical 的 path 都有測試到。
coverage 要高很簡單,全部 function 呼叫一次,然後不要檢查任何東西
coverage 就會 100%,但什麼也沒測試到。
只要關鍵行為都測試到了,不用太糾結 coverage 數字高不高
: 2.
: 直接把他們 include 進來,build failed 就 include,直到 build 過為止
: 這樣的好處是不用去實作 B() C() D() 的 fake,
: 但就會讓整個 unit test 的 dependency 很重
這有時候是合理的作法。
Unit test 是依照"行為"拆分,不是依照 class/function 拆分。
不是一個 function 就對應一個 test,而是以"user 可見的行為" 來拆。
一個功能/行為常常需要多個 functions 組合,這些 private function 都是"實作細節"是沒有必要測試的,你只需要測試 public interface.
同理,一個功能由 A/B/C 三部分組成,A 呼叫 B 和 C,但實際上對外使用者只用 A
那 B/C 可以視為 A 的實作細節,這時候可以只針對 A 做 test
一個 class 的 public API 可以是另外一個 class 的 implementation detail
所以不是一個 class 就要一個 test,實作細節不用測,要測試大的行為。
: 個人偏向1.,畢竟 unit test 就是去測試 function 的邏輯性,
: 在其他 function 對測試 function 沒有 side effect 的情況下(如不會改變某變數的值?
: 將他們 fake 掉而只是單純的去 test 該 function 而已
: 但我第一次接觸,不太知道何時應該去 fake (或 mock) 一個 function QQ
: 我只是有這兩種想法,兩個其實天差地遠XDD
: --
: ※ 發信站: 批踢踢實業坊(ptt.cc), 來自: 114.25.70.74 (臺灣)
: ※ 文章網址: https://www.ptt.cc/Soft_Job/M.1667904696.A.B26
: 推 vi000246: 你可以先讀重構相關的書 11/08 18:53: → GooseLover: 如果模組化有做好,那你1.做得是正確的事情。正常來 11/08 19:12: → GooseLover: 說就是Function跟Process分開測,最後再來個整合測試 11/08 19:12: → GooseLover: 。然後不要抗拒為各別Function寫Unittest 11/08 19:12: 我本來預期就是為個別檔案的個別function寫unit test,不過不確定這樣做是不是有符合u
: nit test的特性
: 推 s06yji3: 單元測試的話1 11/08 19:15: → foreverk: 用1吧,如果要測試的function長文章那樣,那本來就應該 11/08 19:22: → foreverk: 花時間寫BCD的test case 11/08 19:22: 謝謝各位大大,那我可以放心去fake了
: 推 s06yji3: 不知道你用什麼語言,通常會有tool幫你攔截dep的function 11/08 19:28: → s06yji3: 然後去呼叫對應的fake function 11/08 19:28: 應是用google test,沒錯,他可以去呼叫fake function。這部分的實作應該沒什麼問題: 推 MoonCode: 對了 不寫這個測試會怎樣? 11/08 20:14: ※ 編輯: shane87123 (114.25.70.74 臺灣), 11/08/2022 20:15:55
: → ssccg: 合起來測也是種測法,只是那就不是unit test了 11/08 21:14: → angusyu: 專案如果沒有在切介面,直接硬fake會寫到懷疑人生 11/08 21:24: 推 yamakazi: gmock 就是1啊 11/08 22:41: → yamakazi: gmock gtest框架都有了,你想得到的問題大公司都想到了 11/08 22:42: → yamakazi: ,直接整套拿去用就好 11/08 22:42: 推 drajan: 沒切介面就趕快 refactor 沒測試的軟體能跑嗎 11/08 23:01: 推 sniper2824: 1 11/08 23:51: 推 viper9709: 推二樓 11/08 23:57: 推 Lipraxde: 沒出問題的 legacy code 就別想著幫別人加 UT 了,頂多 11/09 00:00: → Lipraxde: 做做整合測試,別把自己搞到懷疑人生 11/09 00:00: 推 lovdkkkk: 不確定目前程式的情況, 假如目前程式很亂, 有可能需要先 11/09 00:17: → lovdkkkk: 做 2 快速加個整合測試, 重構一下, 之後再做 1 11/09 00:17: → leo08210917: 介面切好 弄懂IoC、DI做mock很快 UT也方便 11/09 01:07: → leo08210917: 舊的可以用防腐層切開 弄整合測試就好 11/09 01:08: 推 prag222: 雖我單元測試沒啥經驗,但說真的就是程式太鳥才依賴性 11/09 02:21: → prag222: 太高,相信用物件導向或設計模式都可以切乾淨的 11/09 02:21: → Lipraxde: 只會更糟吧XDDD 11/09 07:22: → bnd0327: 如果BCD沒有被其他函式使用,直接用真的BCD測也無妨 11/09 08:53: 推 wulouise: 2不算UT,但是你在refactor前可能會寫出2那樣的情況 11/09 12:10: → wulouise: 最好先用test framework測整合測試再來refactor 11/09 12:12: 推 andy831020: 絕對是1 最小單元去測試 11/09 15:23: 推 lestibournes: 最近也在工作上嘗試導入,覺得應該是1。但光mock就 11/09 18:28: → lestibournes: 一堆東西,還要擔心測試把程式碼綁死(因為mock/fa 11/09 18:28: → lestibournes: ke的部分已經明確宣告在測試內),還是先硬著頭皮 11/09 18:28: → lestibournes: 先寫了QQ 11/09 18:28: 推 CoNsTaR: 切 dependency 用 mock,有測試環境的問題用 fake 11/09 22:33: → acgotaku: 請善用DI,然後再寫的時候儘量將ABC低耦合 確保你分開測 11/10 01:36: → acgotaku: ABC的時候不需要在mock,做假資料的時候儘量是真實狀況 11/10 01:38: 推 s8952889: 當然是1吧,如果你今天改B的程式碼結果A的單元測試錯了 11/10 12:51: → s8952889: 很奇怪 11/10 12:51: → s8952889: 不過其實在單元測試的檔案寫整合測試也是沒問題的吧 11/10 12:52
--
Sent from PCMan on PCMan's PC
--
Sent from PCMan on PCMan's PC by the author of PCMan -
PCMan.
※ 編輯: HZYSoft (36.225.92.96 臺灣), 11/10/2022 23:27:39
Good
不過實作細節要分到多細還是看個人考量..
不然整個chrome只測UI好像也符合這個分法(?)
推legacy系統要先大範圍integration test。之前摸索時先
搞了些mock物件,弄老半天只測一小塊。直接做必要的fake
然後大塊功能的integration test,至少能測。
因為先有integration test,才成功做了些重構。
同意在缺乏好的模組化跟測試的前提下 整合測試是最優先的
確保最大範圍的抽象行為是正確的再去改內部的程式
推
推
推
推
推推
拜讀
這篇每一段的概念都值得推一次
推
還在那邊想是誰觀念這麼正確...
為什麼全部function呼叫一次就可以達到100% coverag
e?不考慮條件式嗎?
推
推
先推
我們也是先整合再單元,原因就是覺得之後可能會重構
推
pcman 大神推推
推
推
先推再看
推
推
推受用
推
我們公司完全照著這篇文章的觀念在寫unit test
這篇寫的很好 感謝分享
推
受用 推
同意,要測就測抽象行為
推這篇
13
先說在前面 雖然聽起來很幹話,但很多東西沒有標準答案 有時是合適度的問題,也可能是喜好(品味?)的問題 同一個題目,實際的 code 長得不一樣,可能也會用不同的方法處理 另外,除了資源豐富到人力充沛到不行的專案,以及幾乎沒有時程壓力11
大家都選1嗎?我覺得二比較好 Google的guideline是Prefer Realism Over Isolation 詳見 TotT有關fakes的討論也提到16
首Po先說我對 Unit test 的看法:測試單元(可能是 function)的邏輯是否正確 好,進入正題 小弟最近剛工作,稍微讀了一下負責的 project 的程式碼後, 要開始開發 Unit test。 現況是,各個 file (.c) dependency 很重,
爆
[心得] 20年測試版上最近有十年設備的文章 那我也來分享一下20年測試好了 我的學歷是私立五專機械科 五專四年級的時候組了一台PENTIUM-75的桌機 畢業後機械科不知道要做啥 當初還去松山車站附近應徵機車學徒 後來去青輔會學電腦網路 一開始去光華商場附近的茂訊電腦當網路工程師 說好聽是工程師 其實就是客人買電腦之後 我來組裝出貨23
Re: [討論] 怎樣算是一個合格的junior cpp programme針對關於 TDD 的討論另外回一篇好了 覺得用推文太長了 XD : 推 stupidlove0: 朝聖!重要的真的是unit test 08/23 18:47 : → HZYSoft: 回樓上 TDD 問題,TDD 不只要測試,還要先寫測試才寫code 08/23 21:33 : → HZYSoft: 很多人無法習慣這種順序,是否一定要 TDD 這有爭議 08/23 21:3421
Re: [討論] 重構跟kpi的考量如果 A, B 都沒有任何 tests,建議不要動他。 幫 C 實做這個功能的時候,把 unit test 寫好寫滿,確保 C 是對的 行有餘力,針對 A, B 的使用情境也加上 test case,確保未來在 A, B 確實能重用 (這點很重要,否則很容易程式長得很像你以為可以重用,實際上根本不能) 就先做到這樣就好,確保 C 的品質,同時你獲得了高品質的 reusable 模組14
Re: [討論] 做測試的真的這麼慘?測試百百款,這邊回覆一下IC的ATE測試相關。 (俗稱CP、FT的測試,半導體測試廠與其相關) 單做TE就是賺不到大錢也餓不餓死的工作, 不會到慘來形容它,至少相對機會多。 看著現在多半的IC test TE就分主要兩大塊:X
[問卦] test網路測試是這樣的啦 現在line都有好友生日通知 沒道理不知道誰生日吧? 現在過快一小時了 還沒收到任何訊息X
[問卦] 學妹不寫unit test要怎麼辦?如題 明明說好一人負責一部分 結果她寫完 居然沒有寫unit test !! 這是在戲弄肥宅嗎?