單元測(cè)試就是常說(shuō)的Unit Test
而TDD其實(shí)是uTDD - unit Test Driven Development
在我現(xiàn)在的日常工作中,其中一個(gè)很重要職責(zé)就是保證新人快速成長(zhǎng)。這里的“成長(zhǎng)”不是應(yīng)試教育下的快速成長(zhǎng)蒂培,更不是通過(guò)填鴨式教育葵第、題海戰(zhàn)術(shù)來(lái)達(dá)到的成長(zhǎng)怎静。而是以理解公司文化的為前提,“素質(zhì)教育”為基礎(chǔ)的健康成長(zhǎng)集畅。
我們公司的創(chuàng)始人是《敏捷宣言》提出者之一园担,哪怕在這樣一家敏捷絕對(duì)擁躉的科技公司里赁严,也一樣會(huì)有關(guān)于TDD的一些常見(jiàn)問(wèn)題。我在和新人Pair粉铐、帶團(tuán)隊(duì)和
客戶參觀的過(guò)程中都無(wú)一幸免的被問(wèn)到了如下TDD的問(wèn)題:
- 為什么我們要TDD ?
- 任何時(shí)候都要TDD嗎?什么情況下不用TDD?
- TDD怎么衡量她的價(jià)值卤档?實(shí)踐她的都是開(kāi)發(fā)人員蝙泼,她到底有沒(méi)有價(jià)值因該開(kāi)發(fā)人員說(shuō)了算。
這些問(wèn)題的提出者以及提出時(shí)間劝枣,總結(jié)起來(lái)看還挺有意思汤踏。有的完全沒(méi)有接觸實(shí)踐過(guò)敏捷;有的相信敏捷舔腾,但還沒(méi)有付之實(shí)踐溪胶;還有的擁抱后堅(jiān)持實(shí)踐了一段時(shí)間,思考然后稳诚,最終提出反問(wèn)哗脖。
有這些問(wèn)題其實(shí)很正常,回答起來(lái)也不難。我們大可以把TDD的好處羅列一翻才避,把一些正確的大道理再敘述一遍橱夭,但我們前面可是標(biāo)榜過(guò)我們自己是“素質(zhì)教育”,我們更希望對(duì)一些基礎(chǔ)知識(shí)認(rèn)真打磨桑逝,讓大家根據(jù)這些基礎(chǔ)知識(shí)結(jié)合自身的環(huán)境棘劣,給出自己的判斷。學(xué)以致用楞遏,融匯貫通茬暇。
我們這里說(shuō)的TDD(測(cè)試驅(qū)動(dòng)開(kāi)發(fā)),實(shí)際上更準(zhǔn)確的描述為單元測(cè)試驅(qū)動(dòng)開(kāi)發(fā)寡喝。先不談怎么驅(qū)動(dòng)開(kāi)發(fā)糙俗,我們一起來(lái)掀開(kāi)單元測(cè)試的外衣,看看到底本尊長(zhǎng)什么樣拘荡?怎么就可以驅(qū)動(dòng)開(kāi)發(fā)了臼节?他能解決什么問(wèn)題?又對(duì)什么問(wèn)題有心無(wú)力珊皿?
Unit testing is when you write test code to verify units of code.
翻譯起來(lái)就是:單元測(cè)試就是用來(lái)驗(yàn)證代碼單元正確性所寫的測(cè)試代碼
我們下面站在 先實(shí)現(xiàn)后測(cè)試 的原生視角來(lái)回答幾個(gè)問(wèn)題
“單元”到底怎么定義网缝?
- 在尺寸上并沒(méi)有清晰的定義。
- 一小段展現(xiàn)出某些“有用的行為”的代碼
- 一個(gè)單元自身 通常 不表示完整的端對(duì)端(end-to-end)行為蟋定,它只表示這個(gè)端對(duì)端行為中的一個(gè)子部分粉臊。
可以看出這里的“單元”,并沒(méi)有固定和清晰的定義驶兜,比較容易接受的定義是把“單元”和函數(shù)劃上等號(hào)扼仲。項(xiàng)目管理中所有的實(shí)踐,最終都是為了保證項(xiàng)目的按時(shí)交付及
質(zhì)量保證抄淑。而且明確說(shuō)明單元測(cè)試不因該表示完整的端對(duì)端行為屠凶,因?yàn)樵陧?xiàng)目的測(cè)試體系里,比如金字塔原理肆资,越接近用戶的測(cè)試往往是最費(fèi)時(shí)的矗愧,所以從成本和質(zhì)量平衡的角度來(lái)看,因該是越精簡(jiǎn)越好郑原,這其實(shí)就是對(duì)單元測(cè)試提出了明確的要求-集成測(cè)試和端到端測(cè)試沒(méi)有覆蓋到的唉韭,那么單元測(cè)試你就給我保證好,至于你用函數(shù)分還是以行為分犯犁,沒(méi)有統(tǒng)一的標(biāo)準(zhǔn)属愤。這里借助絕對(duì)正確的一句廢話-對(duì)項(xiàng)目合適的才是最好的。
何時(shí)酸役、何故需要寫單元測(cè)試住诸?
- 你 剛剛 完成了一個(gè)特性(Feature)的編碼并且想確保它能夠按照預(yù)期工作驾胆。
- 你想用文檔記錄一個(gè)代碼中的修改,以便你或其他人能夠在以后明白相關(guān)的意圖只壳。
- 你需要修改代碼俏拱,同時(shí)希望確保這些即將來(lái)臨的修改不會(huì)破壞任何已經(jīng)存在的行為。
- 你希望了解當(dāng)前系統(tǒng)中的行為吼句。
- 你希望知道第三方代碼的行為在什么時(shí)候會(huì)與你的期望不符锅必。
簡(jiǎn)單來(lái)說(shuō)也就是對(duì)測(cè)試特性的另一種描述,通常我們可以把測(cè)試當(dāng)成文檔惕艳,因?yàn)閱卧獪y(cè)試要足夠的簡(jiǎn)單搞隐,不然就會(huì)有人問(wèn)這樣的問(wèn)題:我們用什么來(lái)保證測(cè)試本身的正確性呢?是不是得為我們的測(cè)試再寫測(cè)試呢远搪,顯然不是劣纲,不然不就死循環(huán)了嘛。但這不意味著我們就不用保證測(cè)試本身的正確性了谁鳍,簡(jiǎn)潔性其實(shí)就是這個(gè)目的癞季,你一眼就能看出來(lái)正確與否,那么我們大家都有信心相信我們測(cè)試代碼的質(zhì)量倘潜,以及功能模塊的穩(wěn)定性也可以通過(guò)測(cè)試得到了因有的保障绷柒。
推薦的測(cè)試結(jié)構(gòu)
- AAA (Arrange - Act - Assert)
- GWT (Given - When - Then)
需要注意的是,通常我們建議從結(jié)果開(kāi)始(Then/Assert)涮因,明確我們希望得到的結(jié)果废睦,再設(shè)置好測(cè)試環(huán)境并觸發(fā)相應(yīng)的動(dòng)作。
推薦的測(cè)試原則 - FIRST
- Fast : 好的測(cè)試因該足夠快 - 因?yàn)閱卧獪y(cè)試的價(jià)值在于持續(xù)养泡、全面嗜湃、快速的反饋系統(tǒng)的健康程度
- Isolated: 好的測(cè)試因該相互隔離 - 你應(yīng)當(dāng)能夠在任何時(shí)間,以任何順序澜掩,運(yùn)行任何一個(gè)測(cè)試购披。
- Repeatable:好的測(cè)試應(yīng)該可復(fù)驗(yàn) - 每一個(gè)測(cè)試應(yīng)當(dāng)在每一次運(yùn)行時(shí)產(chǎn)生與之前一樣的結(jié)果。
- Self-Validating - 好的測(cè)試應(yīng)該能夠自認(rèn)證肩榕!- 寫測(cè)試是為了節(jié)省時(shí)間而不是為了花費(fèi)更多的時(shí)間今瀑。所以,測(cè)試應(yīng)當(dāng)能夠自排列点把、及時(shí)、恰到好處的自動(dòng)化運(yùn)行屿附,并且能夠快速郎逃、準(zhǔn)確的確認(rèn)結(jié)果,盡可能的不需要手動(dòng)操作或設(shè)置挺份。
- Timely - 好的測(cè)試應(yīng)該足夠及時(shí)褒翰!- 單元測(cè)試是一個(gè)好習(xí)慣,你越是推遲利用單元測(cè)試來(lái)驗(yàn)證你的代碼,就越是需要付出更多的代價(jià)优训。同理朵你,一旦你將代碼提交進(jìn)了代碼庫(kù),你專門找時(shí)間回過(guò)頭來(lái)補(bǔ)測(cè)試的機(jī)會(huì)也就很小了揣非。
推薦的測(cè)試邊界原則 - CORRECT
- Conformance - 一致性 (值是否符合預(yù)期的格式抡医?)
- Ordering - 有序性 (一組值的順序是否符合預(yù)期?)
- Range - 區(qū)間性 (值是否在一個(gè)合理的最大值和最小值的范圍內(nèi)早敬?)
- Reference - 引用性 / 耦合性 (代碼是否引用了一些不受其直接控制的外部因素忌傻,由這些外部因素所引入的前置條件或后置條件所造成的影響是否符合預(yù)期?)
- Existence - 存在性 (值是否存在(例如:非 null搞监,非零水孩,存在于某個(gè)集合中等)? )
- Cardinality - 基數(shù)性 : 計(jì)數(shù)性 (是否恰好有足夠的值?(重點(diǎn)關(guān)注 0-1-n 原則琐驴,問(wèn)題往往發(fā)生在這三個(gè)邊界上俘种。))
- Time - 時(shí)間性(絕對(duì)時(shí)間及相對(duì)時(shí)間)- (所有事情是否按順序發(fā)生?是否在正確的時(shí)間绝淡?是否及時(shí)宙刘?)
結(jié)束語(yǔ)
從單元測(cè)試的基本概念可以看出來(lái),更多的情況下够委,并沒(méi)有嚴(yán)格意義上的定義荐类,更應(yīng)該堅(jiān)持原則,看清形勢(shì)茁帽,找到最適合項(xiàng)目團(tuán)隊(duì)的玉罐。
TDD也可以簡(jiǎn)單的看作基于單元測(cè)試,所采用的敏捷實(shí)踐之一潘拨,持續(xù)改進(jìn)也是他們不謀而合的地方吊输,也是我推薦TDD的原因之一。
下一篇會(huì)以TDD實(shí)例從代碼實(shí)踐來(lái)講解因該怎么做TDD铁追。
歡迎更多的討論季蚂,更浩渺的思維!
可通過(guò)以下方式聯(lián)系我們(You can contact us the ways below):