TDD三定律
- You must write a failing unit test before you write production code.
單元測試代碼先于生產(chǎn)代碼 - You must stop writing that unit test as soon as it fails; and not compiling is failing.
單元測試一旦失敗,開始寫生產(chǎn)代碼 - You must stop writing production code as soon as the currently failing test passes.
老測試一旦通過,返回寫新測試
單元測試好處
單元測試讓代碼可擴(kuò)展、可維護(hù)、可復(fù)用。原因很簡單,有了測試,你就不用擔(dān)心對代碼的修改。如果沒有測試,每次修改都可能帶來缺陷。無論代碼設(shè)計(jì)的多么符合規(guī)范,可擴(kuò)展性多么強(qiáng)。如果沒有測試,你就很難對代碼做改動。因?yàn)槿四X與計(jì)算機(jī)不同,它無法保證考慮到所有分支所有場景。
如何寫好單元測試
可讀性、可讀性、還是tmd可讀性。在單元測試中,代碼的可讀性甚至比生產(chǎn)代碼還要重要。明確、簡潔、并有足夠的表達(dá)力。借用翻譯的金標(biāo)準(zhǔn),也就是盡力區(qū)做到“信達(dá)雅”。
測試一般可以分成3個環(huán)節(jié):
- 構(gòu)造 根據(jù)覆蓋目標(biāo)的不同和覆蓋源程序語句的詳盡程度,構(gòu)造數(shù)據(jù)的覆蓋方式又可分為: 語句覆蓋(SC) 判定覆蓋(DC) 條件覆蓋(CC) 條件/判定覆蓋(CC) 條件組合覆蓋(MCC) 修正判定條件覆蓋(MCDC) 點(diǎn)覆蓋 邊覆蓋 路徑覆蓋。選取適合自己項(xiàng)目的覆蓋方式。
- 測試 測試即使用構(gòu)造數(shù)據(jù)輸入待測試單元并運(yùn)行的過程。
- 檢驗(yàn) 校驗(yàn)是單元測試價(jià)值的真正體現(xiàn)。如果沒有校驗(yàn)過程,那么一切構(gòu)造、一切運(yùn)行都沒有意義。使用assert語句,判斷輸出是否符合預(yù)期。值得注意的是,F(xiàn)alse或者Error也是預(yù)期的一種。
單元測試原則
雙重標(biāo)準(zhǔn)
單元測試與生產(chǎn)代碼,分屬不同場景。應(yīng)遵循不同的工程標(biāo)準(zhǔn)。例如,生產(chǎn)代碼是運(yùn)行在嵌入式系統(tǒng)上,那么就要追求極簡、高效,用于匹配嵌入式系統(tǒng)有限的資源。測試環(huán)境中完全沒有必要考慮此類情況。重點(diǎn)是,代碼整潔可讀是所有代碼共同的要求。
斷言
有一種說法,每個測試函數(shù)都要有一個斷言語句。這種規(guī)則看起來苛刻,實(shí)際上好處多多。首先是代碼整潔可讀,每個斷言代表一個測試的結(jié)束。其次,在攔截意外之時(shí),你的測試用例將更加有效。
F.I.R.S.T
- Fast(快速) 測試代碼必須要能夠快速運(yùn)行。如果測試代碼運(yùn)行緩慢,則會成為開發(fā)的累贅。只有1min以內(nèi)能跑完的測試,開發(fā)者才會頻繁運(yùn)行,從而從容清理錯誤代碼。
- Independent(獨(dú)立) 測試應(yīng)相互獨(dú)立。刪除或增加用例不應(yīng)對其他用例產(chǎn)生影響。如果測試用例相互依賴,一個用例出錯會導(dǎo)致一連串的錯誤,定位將變得無比復(fù)雜。
- Repeatable(可重復(fù)) 測試應(yīng)該能在任何環(huán)境在任何時(shí)間通過。如果測試不能永遠(yuǎn)正確,那么你就總有解釋失敗的借口。
- Self-Validating(自足驗(yàn)證) 測試用例應(yīng)該有布爾輸出,成功或者失敗,絕不應(yīng)該在日志中判斷。
- Timely(及時(shí)) 測試用例應(yīng)及時(shí)編寫。就如TDD原則,在生產(chǎn)代碼之前,測試代碼就應(yīng)該寫完。
軟件開發(fā)過程中,問題發(fā)現(xiàn)的越晚,修復(fù)成本就會越高。單元測試,是發(fā)現(xiàn)問題最早時(shí)機(jī)(如果不算代碼檢視的話)。做好單元測試,前期可能代碼量將會增加一倍。但無論對于代碼重構(gòu)還是未來的代碼維護(hù),單元測試必然是無可或缺的一部分。