學習筆記 第一部分 測試驅動開發基礎

2021-07-09 08:07:49 字數 4061 閱讀 9316

test-driven development,驅動測試開發,是一種軟體開發的開發方式.

它要求在編寫某個功能**之前先編寫測試**,然後只編寫使測試通過的功能**,通過測試來推動整個開發的進行.

我在學習的過程中感覺收穫良多,因此將學習的過程和心得體會記錄下來,希望對想要學習了解tdd的朋友也能提供一些幫助.

因為tdd的規則跟傳統的開發方式不同,所以如果要使用tdd,就得轉變以前的傳統觀念.這一點其實挺難的

以使用者的角度來在外部測試應用,可以寫乙個小故事,來模擬使用者的整個操作流程,根據這個流程來寫出測試**,從這個角度上說功能測試可以看作是你開發的應用(或者模組)的乙份使用說明書

功能測試可以只在乙個模組內,也可以包含多個模組,不過按道理講使用者是不了解也不需要了解他們需求的功能是在乙個模組內還是包含多個模組的,所以我認為功能測試應該是乙個全域性的測試方式

功能測試也叫驗收測試,端對端測試,黑盒測試

功能測試使用的主要的工具是selenium,乙個可以控制瀏覽器行為的工具集

以程式設計師的角度從內部來測試應用,測試的內容是某個模組內部的具體實現

單元測試只負責測試某個模組內的功能

先借用書中的一張圖來有乙個直觀的印象

遍寫乙個功能測試

從使用者角度用故事的方式來描述新功能,將故事翻譯成測試**

執行功能測試

如果功能測試出錯,就考慮如何編寫應用**來通過測試,

如果功能測試出現的異常是預料中的,其實是好事,至少我知道下一步的工作是什麼

如果功能測試出現了非預期的異常,需要仔細閱讀出錯**,很可能是因為之前的修改導致了更多的錯誤.可以通過多種方式來除錯**:

編寫乙個(多個)單元測試

針對上一步想到的編碼方式,編寫對應的單元測試

執行單元測試

編寫應用**

針對單元測試提示的錯誤來編寫盡可能少的應用**,僅僅是為了通過這次測試

迴圈第3,4,5步,直到通過全部單元測試並且覺得能通過第1步編寫的功能測試

執行第1步所編寫的功能測試

如果能通過,則可以向前一小步了

如果不能通過,可能需要編寫更多的單元測試和應用**,繼續迴圈第3,4,5步

重構**

不修改**的功能而又對**進行修改的過程就叫重構

當通過單元測試或功能測試時考慮是否需要重構**,注意在重構的過程中也要遵循tdd的規則,每重構一小步就要執行一次測試,一直到重構完成.當測試全部通過時,又回到第1步(或第3步)

重構**也包括修改單元測試的**,但是注意修改測試**和修改應用**不能同時進行

以上的流程看起來很繁瑣,也很無趣,還很浪費時間,但是我覺得這樣做有他的道理和好處

保持編碼的連續性,當功能測試寫好以後,整體目標就定下來了,以後的工作就是根據測試提示的錯誤來一步一步的接近目標,而不會受到其他的影響,比如在實現功能的過程中又有其他的想法,轉而開發其他的模組,也不會過早地進行重構

在整個開發過程中只需要考慮怎麼通過測試就好了,不需要考慮太多的其他問題,這樣的開發過程也會相對輕鬆

整個開發過程都受到單元測試的保護,保證不會出現錯誤,也不會破壞以前已經實現了的功能和模組

在開發簡單功能時會感覺很無趣,但是當**結構已經很複雜時,可以避免被複雜的**攪暈

kent beck有乙個很好的比喻,開發的過程就像是從井裡打水,當井不深水桶也不夠滿時,這個過程很容易,但如果要從乙個很深的井裡面打一桶很滿的水,這個過程就很困難了.而tdd就像在井口安裝的乙個棘輪,它不一定能讓你打水更輕鬆,但能讓你在打水的過程中能稍事休息,還能保證你的水桶不會突然滑下去.就像打rpg遊戲時的sl**一樣(這個比喻是我想出來的^_^)

tdd是一種紀律,如果不一開始就對你要求嚴格,以後你對自己的要求會越來越鬆的

這是tdd最基本的規律,在做任何事情之前(新增功能,修改功能,重構**),都要先把測試**寫好.一開始會感覺這種方式***又浪費時間,其實在熟練運用以後會體會到這樣開發的好處

當功能測試通過後需要新增新的功能時,不要想太遠,只向前走一小步,新增一點點新的功能就好.

當單元測試失敗時,只改動最少的**量(一次一行)以通過當前測試就可以了

我每次寫**都會忍不住把想到的都寫出來,想改的都改完,這樣的結果就是經常把**搞得一團糟,連以前已經實現的功能都不能正常執行了.反而會花更多的時間來除錯混亂的**.

關於每次只改動最少的**量這個問題我是這樣來理解的,每次改的最小**量指的是你最容易控制的**量,不一定非得只能是一行

比如說views裡面缺少乙個方法home_page來處理乙個url,對於初學者,修改迭代的步驟是這樣的:

# 第一步,定義乙個home_page空物件

home_page = none

# 第二步,將home_page空物件改為乙個空方法

defhome_page

():pass

# 第三步,對home_page方法新增必須的引數

defhome_page

(request):

pass

# 第四步,修改home_page方法的返回值,使之返回httpresponse物件

# 第五步,返回正確的響應

但是對於乙個已經熟練掌握django的程式設計師來說,我認為直接寫成如下形式是沒問題的

def

home_page

(request):

pass

基本的規則就是當需要改功能加功能或者重構之前,先commit一次

因為我依賴ide的history功能,所以commit得沒那麼頻繁

在做任何改動之前先寫測試,如果你因為自以為**邏輯簡單就忍不住越寫越多,當你意識到**足夠複雜時,你已經是那只被煮熟的青蛙了.

每個單元測試的方法要盡可能的小,每個測試方法只測試一件事情

這樣的方式會讓你在測試失敗時輕鬆定位失敗的原因

並且如果當測試方法中前面的測試出錯時,你也不知道後面的測試是否通過

單元測試的目的是測試邏輯,執行流控制,配置等,而不是測試常量.如果在應用**裡寫了

wibble =3
這時如果寫這樣的測試**就沒有多大意義了

assert wibble ==3
如果需要測試html字串,將html字串寫在模板(templates)裡面

在重構完成之前一定不能增加或修改功能,重構就只是重構,這也是我之前在開發時經常會犯的錯誤,經常在重構時又搞到其他地方去了.同樣的道理,在重構沒有完成之前也不要修改測試**

當第一次複製已有的**時(這樣相同**就出現了兩次),忍了,不要急著來重構它

當再一次複製相同的**時,這時相同的**已經重複三次了,重構吧,注意重構之前先commit一次**

遵循這個原則可以避免過早的重構**

如果在寫測試**或編碼時突然有什麼新的想法,盡量不要中斷當前的工作

拿一張便條或者在todo文件中記錄下來,等這輪unit-test/code週期完成後,再來處理

或者等功能測試通過後,新增為新的功能

yagni(you aint gonna need it!)意為你不需要它.每個開發人員都樂於創造,有時很難壓抑馬上實現一些頭腦中突然冒出來的想法的衝動,但這些想法很可能是不需要的.

因此在剛開始設計應用時不要設計得太複雜,功能也不要太多,只要設計最基本的功能就好了

更複雜的設計和功能在開發中根據現實的需求逐漸加入.

這一點我覺得很有道理,以前在早期設計時總想著如何把所有可能的功能和需求都考慮到,浪費了很多的時間和精力,但真正在開發中會發現需求在不斷地變化,以前設計的很複雜的模型可能根本就沒用.

pip3

install--

upgrade

selenium

此文包含書中的第1-6章,每一章的**對應**庫中的乙個分支,其

linux筆記第一部分

開源系統,可以自由傳播,目前後台服務端絕大部分都是linux程式執行平台,主要是因為以下幾點 unix的優秀特性 linux的常用版本redhat和centos,目前主流使用的centos7 centos6安裝鏈結 因linux不同於windows,所以linux事實上並沒有和windows一樣的c...

Django學習 第一部分

建立並啟用虛擬環境後,在shell提示符這下輸入命令 pip install django 可以去看官方教程非常詳細 在教程中會引導你完成基本的輪詢應用程式的建立 它有兩部分組成 python m django versoin如果安裝了django,我們可以看到安裝的版本,如果沒有將會受到類似 no...

Axure RP 第一部分

axure rp是乙個專業的快速原型設計工具。axure 發音 ack sure 代表美國axure公司 rp則是rapid prototyping 快速原型 的縮寫。axure rp是美國axure software solution公司旗艦產品,是乙個專業的快速原型設計工具,讓負責定義需求和規格...