TDD in .NET Core - 简介
本文很多內(nèi)容來(lái)自選自TDD實(shí)例一書(shū)。
預(yù)備知識(shí)
最好有一些預(yù)備知識(shí),例如xUnit,Moq,如何編寫(xiě)易于測(cè)試的代碼,這些內(nèi)容我都寫(xiě)了文章:https://www.cnblogs.com/cgzl/p/9178672.html#test。
?
Test Driven Development
什么是TDD(Test Driven Development)?
TDD是一個(gè)軟件開(kāi)發(fā)過(guò)程,這個(gè)過(guò)程依賴于重復(fù)性的小開(kāi)發(fā)周期:需求被轉(zhuǎn)化為具體的測(cè)試用例,然后改進(jìn)程序以便通過(guò)測(cè)試。
?
在TDD里有兩條規(guī)則:
- 只在有未通過(guò)的自動(dòng)化測(cè)試的情況下,你才會(huì)去寫(xiě)新的代碼
- 消滅重復(fù)
?
這兩條規(guī)則在技術(shù)上的含義是:
- 你必須進(jìn)行良好的設(shè)計(jì),運(yùn)行的代碼可在決策之間提供反饋
- 開(kāi)發(fā)人員得寫(xiě)自己的測(cè)試
- 開(kāi)發(fā)環(huán)境可以針對(duì)微小的變化需要提供快速的響應(yīng)
- 您的設(shè)計(jì)必須由眾多高內(nèi)聚、低耦合的組件組成,這樣測(cè)試會(huì)更簡(jiǎn)單。
?
這兩條規(guī)則也意味著編程的三個(gè)任務(wù):
Red,Green,Refactor,這就是TDD的咒語(yǔ)。
?
如果TDD可以很好的執(zhí)行,那么它就會(huì)大幅度減少代碼缺陷的密度,也使工作的主題對(duì)于相關(guān)人員來(lái)說(shuō)更加清晰。所以,TDD也具有社會(huì)含義:
- 如果缺陷密度可以降低到足夠的程度,那么QA就會(huì)從被動(dòng)變?yōu)橹鲃?dòng)的工作。
- 如果那些“讓人討厭的驚喜”可以減少到足夠的程度,那么項(xiàng)目經(jīng)理就可以精確的評(píng)估以便讓客戶參與到每日的開(kāi)發(fā)工作中。
- 如果技術(shù)會(huì)議的主題足夠清晰,那么程序員就會(huì)按分鐘去工作而不是按天或周來(lái)安排和進(jìn)行工作。
- 如果缺陷密度可以降低到足夠的程度,那么我們每天都可以交付出具有新功能的軟件,這就會(huì)與客戶建立新的業(yè)務(wù)關(guān)系。
?
這些概念都很簡(jiǎn)單,但是動(dòng)機(jī)是什么?為什么開(kāi)發(fā)人員要去寫(xiě)自動(dòng)測(cè)試代碼?為什么開(kāi)發(fā)人員在他們的思維能夠大幅飆升的設(shè)計(jì)時(shí),卻只進(jìn)行小步工作? 勇氣。
?
勇氣
TDD是編程過(guò)程中管理恐懼的一種辦法。
這個(gè)恐懼不是壞事,它是一種合理的恐懼,例如:”這個(gè)問(wèn)題確實(shí)很難,我從開(kāi)始的感覺(jué)看不到盡頭“。
如果疼痛是喊停的自然表達(dá),那么恐懼就是告訴你要“小心”。
?
小心是很好的,但是恐懼還有一些其它的影響:
- 讓你不得不進(jìn)行更多試探性操作
- 讓你交流的更少
- 讓你羞于反饋
- 讓你脾氣暴躁
這些影響在開(kāi)發(fā)的時(shí)候?qū)δ愣紱](méi)有任何幫助,尤其是遇到困難問(wèn)題的時(shí)候。那么你如何面對(duì)困難處境并且:
- 取代嘗試/試探,而是盡快進(jìn)行具體學(xué)習(xí)
- 取代爭(zhēng)吵,而是進(jìn)行更清楚的溝通
- 取代避免反饋,而是尋求幫助,和具體的反饋
- 控制你自己的脾氣
TDD會(huì)管理這些事情。
?
為什么要TDD
從業(yè)務(wù)角度:
- 提供了需求的確認(rèn)。通過(guò)編寫(xiě)測(cè)試以及RGR周期,需求確認(rèn)很自然的在軟件開(kāi)發(fā)的過(guò)程中就完成了。
- 捕獲回歸問(wèn)題。回歸問(wèn)題就是指隨著軟件新功能的發(fā)布,以前的某些功能卻不好用了。TDD可以很早的發(fā)現(xiàn)回歸問(wèn)題。
- 綜上兩點(diǎn),TDD也降低了維護(hù)成本。
?
從開(kāi)發(fā)人員角度講,TDD還有以下好處:
- 設(shè)計(jì)為先的心態(tài)。寫(xiě)測(cè)試的時(shí)候,我們就得考慮與軟件的交互應(yīng)該如何實(shí)現(xiàn),以便把這些功能需求編程可能。
- 防止過(guò)度工程。關(guān)注于如何讓測(cè)試通過(guò)和滿足客戶的期待,就會(huì)讓我們保持正軌,而不是迷失于架構(gòu)設(shè)計(jì)和幻想那么無(wú)法提供很多價(jià)值的最佳抽像設(shè)計(jì)中。
- 增加開(kāi)發(fā)人員的動(dòng)力。取代了花費(fèi)幾天時(shí)間想盡辦法來(lái)實(shí)現(xiàn)某個(gè)功能這樣的操作,TDD把需求分解成一些測(cè)試,并結(jié)合RGR流程,這就允許你可以持續(xù)快速的進(jìn)展并建立成功循環(huán)。
- 收獲自信。通過(guò)大量的測(cè)試結(jié)果,你感動(dòng)支配的力量,無(wú)論修改、重構(gòu)、增加功能都變得很簡(jiǎn)單。
?
第一個(gè)實(shí)例
在本例中,您將會(huì)看到TDD的如下步驟:
?
建立.NET Core 項(xiàng)目
這個(gè)很簡(jiǎn)單,首先建立一個(gè)Console App:
?
然后再添加一個(gè)xUnit項(xiàng)目:
?
這個(gè)測(cè)試項(xiàng)目需要引用Console項(xiàng)目。
?
需求
有這樣一份報(bào)表:
?
現(xiàn)在想要做成支持多幣種的:
?
這里還提供了匯率:
?
目標(biāo)就是產(chǎn)生第二張圖那樣的報(bào)表。
?
開(kāi)始操作
我們需要做哪些工作?
- 讓兩種幣種的錢(qián)數(shù)可以進(jìn)行加法操作,并通過(guò)給定的匯率算出結(jié)果。
- 讓股票單價(jià)可以乘以股票數(shù)并得出總額。
上面是一個(gè)待辦問(wèn)題列表(To-Do List)。我們就關(guān)注于這個(gè)待辦列表即可。
列表里的問(wèn)題應(yīng)該是逐個(gè)解決的,解決完一個(gè)劃掉一個(gè);如果有新問(wèn)題,就在后邊加上一條。
?
編寫(xiě)測(cè)試
下面我們開(kāi)始,先不建立對(duì)象,先寫(xiě)測(cè)試:
?讓編譯通過(guò)
這里有很多問(wèn)題,編譯也無(wú)法通過(guò),這些問(wèn)題我們也是一個(gè)一個(gè)來(lái)解決。
1. 首先,沒(méi)有Dollar這個(gè)類(lèi),那就建立Dollar這個(gè)類(lèi):
第一個(gè)問(wèn)題解決了。
?
2. 沒(méi)有相應(yīng)的構(gòu)造函數(shù),那就建立構(gòu)造函數(shù):
又解決了一個(gè)問(wèn)題!
?
3. 沒(méi)有Times()這個(gè)方法,那就建立該方法:
又解決了一個(gè)問(wèn)題!
?
4. 沒(méi)有Amount屬性,建立該屬性:
編譯問(wèn)題都解決了!!
?
看一下測(cè)試方法:
編譯錯(cuò)誤肯定是沒(méi)有了。
?
測(cè)試Fail
然后跑測(cè)試:
不出意料肯定會(huì)Fail。
?
讓測(cè)試通過(guò)
現(xiàn)在有了具體的這個(gè)Fail的測(cè)試,我們現(xiàn)在的任務(wù)就是讓該測(cè)試變成Pass,而不是實(shí)現(xiàn)多幣種報(bào)表,先讓這個(gè)測(cè)試通過(guò),再慢慢讓其它測(cè)試通過(guò)。
您可能不喜歡這樣,但是現(xiàn)在的目標(biāo)不是做出完美的解決方案,目標(biāo)就是讓這個(gè)測(cè)試通過(guò),所以這時(shí)候代碼可能很爛:
我寫(xiě)死了數(shù)字10。
然后再跑測(cè)試:
測(cè)試Pass了!!
?
重構(gòu),移除重復(fù)
別著急,周期還沒(méi)結(jié)束。
現(xiàn)在,我們需要移除重復(fù)。但是重復(fù)在哪?
通常你看到的重復(fù)是指代碼的重復(fù),這里是指測(cè)試中的數(shù)據(jù)和代碼中數(shù)據(jù)的重復(fù)。
這個(gè)10是哪來(lái)的? 它實(shí)際上是:
是通過(guò)5乘以2得來(lái)的。
所以代碼中的5*2和測(cè)試中的5*2是重復(fù)的。 我們需要移除這個(gè)重復(fù),但是可能需要不止一步來(lái)實(shí)現(xiàn)。
?
先把乘法移動(dòng)到Times方法里試試:
這樣的話,測(cè)試仍然會(huì)pass:
這是一小步。
?
那么5是哪里來(lái)的?
應(yīng)該是從構(gòu)造函數(shù)傳遞進(jìn)來(lái)的,我們可以把它存到Amount屬性里:
所以我們可以在Times方法里使用它:
?
現(xiàn)在處理這個(gè)2,它應(yīng)該可以使用參數(shù)multiplier代替:
OK!
?
此外,我們可以對(duì)代碼的語(yǔ)法進(jìn)行一些優(yōu)化:
其實(shí)某些優(yōu)化也應(yīng)該通過(guò)TDD的RGR周期來(lái)實(shí)現(xiàn)。
?
第一篇文章就簡(jiǎn)單介紹這些。
?
轉(zhuǎn)載于:https://www.cnblogs.com/cgzl/p/9655053.html
總結(jié)
以上是生活随笔為你收集整理的TDD in .NET Core - 简介的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: python中sorted和.sorte
- 下一篇: 设计模式——10.单例模式