為什么要做單元測試
通常我們在做任何工作會先考慮它的回報,編寫代碼更是如此。如果單元測試的作用不大,沒有人會願意再寫一堆無用的代碼,那么單元測試到底能夠給我們帶來什么優點呢?如下:
- 便於后期重構。單元測試可以為代碼的重構提供保障,只要重構代碼之后單元測試全部運行通過,那么在很大程度上表示這次重構沒有引入新的BUG,當然這是建立在完整、有效的單元測試覆蓋率的基礎上。
- 優化設計。編寫單元測試將使用戶從調用者的角度觀察、思考,特別是使用TDD驅動開發的開發方式,會讓使用者把程序設計成易於調用和可測試,並且解除軟件中的耦合。
- 文檔記錄。單元測試就是一種無價的文檔,它是展示函數或類如何使用的最佳文檔,這份文檔是可編譯、可運行的、並且它保持最新,永遠與代碼同步。
- 具有回歸性。自動化的單元測試避免了代碼出現回歸,編寫完成之后,可以隨時隨地地快速運行測試,而不是將代碼部署到設備之后,然后再手動地覆蓋各種執行路徑,這樣的行為效率低下,浪費時間。
等等,講了這么多優點,無非就是良好的接口設計、正確性、可回歸、可測試、完善的調用文檔、高內聚、低耦合,這些優點已經足以讓我們對單元測試重視起來了,但是個人覺得還有更重要的原因。
- 首先,帶來自信。在接手一個新的項目,或者說是參與一個新的項目開發時,往往這種情況是你半途參加進去的,你需要對已有的代碼結構進行解讀和理解,對於業務的理解,對於代碼個中各個模塊關系的理解。如果一開始就理財出錯,很可能修改后的代碼會引起更多的BUG出現,到那時候又需要修復更多的BUG,改了一個地方,很有可能會莫名其妙地影響另外一個地方,這種現象是很常見的。還有一種情況,假設你修改的功能沒問題,但是需要去測試驗證,在測試的時候就需要考慮這個功能點它原有的測試路徑有哪些,又需要一一去驗證功能路徑,以證明本次修改對於已存在的功能點不造成影響。這其中就存在着很大的時間成本,導致效率不高。那是否存在着這么一種方式,我需要修改我想改動的地方,不需要關心修改完之后它所造成的影響,也不需要關心它的測試回歸性,有,此時就是單元測試登場的時候。寫單元測試代碼,可以讓我自己寫的代碼足夠自信,它是經得起考驗的。
- 其次,更快反饋。對於有一定編程經驗的開發人員來說,當他拿到一個新需求的時候,首先想到的不是動手 Coding ,而是會先想想代碼的結構,有些類,數據結構該是如何,然后才開始敲代碼。如果沒有單元測試,一般流程基本是這個模塊功能全部寫完才開始測試,比如利用 MVP 架構的功能。一般都是開始 Model 模塊,然后完善 Presenter 模塊,最后寫 View 模塊,等這幾個模塊都寫完了,再把 APP 跑起來,驗證自己寫的功能模塊是否符合需求,沒有符合則繼續回去修改代碼,這中間需要花費很長的時間才能知道當下自己寫的代碼是否符合要求,是否正確。那有沒有一種即時反饋的方式呢,有,寫單元測試即可,當你寫完一個函數,馬上就匹配一個單元測試函數,這樣即寫即測的方式可以保證你當場寫的代碼馬上進行修改,測試通過一個,就表示完成一個小的功能點,最后,把函數組裝起來,就是我們想要大的功能點。
- 最后,節約時間。對於 Android 開發來說,一遍一遍的運行 APP ,然后執行相應的用戶操作,看界面是否正確的顯示,通過這種方式來測試功能,其實是非常浪費時間,而且效率不高,而用單元測試,可以幾乎不用打開 APP 來執行,當然有些需要一些資源文件的是需要 APP 運行條件,絕大部分的功能在單元測試階段就能驗證完畢,那么速度就相對快很多。此外,單元測試還能幫忙減少 BUG ,從而減少調試 BUG 的時間,一些低級犯的錯誤在單元測試階段就能避免掉。
不寫單元測試借口
很多開發人員不寫單元測試,最重要的一個原因是他們並不知道單元測試能夠帶來什么好處,甚至根本不了解單元測試這個詞,那自然就像平行線般與之毫無交集。還有一個比較重要的原因是一些開發人員的編程思想還處在一個相對初級的階段,開發軟件只管實現功能,什么高內聚、低耦合、重構、設計、可測試等認為太過專業,對於這些名詞以及意義還不了解,這自然不會考慮使用了。還有一些非思想層面的理由,如下:
- 單元測試太花時間了。軟件開發工作那么忙,代碼都寫不完哪有時間寫單元測試。這可能是開發人員用的最多的借口,從某些方面來說,這不能算借口,因為很多開發人員確實在工作上投入的時間特別多。但真的是這樣的嗎,你有沒有想過,導致加班的原因也許就是花了太多時間在手動測試、調試程序上:或許你沒有考慮到靈活性與設計,使得在需求發生變更時你需要花很多時間在復雜的代碼堆中完成特定的功能,而這些修改又可能引入新的 BUG ,又將導致你需要進行耗時的手動測試、調試等等,如此反復,代碼將變得越來越亂,越來越難以維護,最終導致無休止的加班。
- 測試不是我的工作。測試確實不是開發人員的工作,但單元測試確實是開發人員的工作,測試包含很多種,而只有單元測試是開發人員的工作范疇。開發人員為應用編寫代碼,那么自然需要保證代碼的正確性,而單元測試正是這種保證代碼正確性的白盒測試,也就是在了解代碼內部結構邏輯的情況下進行有目的的測試,既然說到了解代碼,那么開發者自然是最權威的人。因此,編寫單元測試並且為測試人員提交正確的代碼進行其他測試是開發人員的職責所在。
- 代碼都編譯通過了,還測什么。一般來說,這是一個不會放在嘴上但可能藏在心里的借口。代碼編譯通過只能說你寫的代碼符合語法要求,並不代表能保證正確性。
- 代碼原來就沒有單元測試,並且難以測試。這個問題基本是接受和維護別人開發的代碼,而原來的代碼本身就沒有單元測試了,再加入如果代碼的耦合性較高,那么就更難以為這些代碼寫單元測試。此時正是你了解代碼時候,首先為能夠測試的部分添加單元測試,保證這些可測試的部分不會被污染,然后在對代碼有足夠的了解之后再對代碼進行重構,降低代碼的耦合性,並且慢慢補充測試用例,使得代碼的耦合性、可測試性慢慢建立起來。
