先測試再開發?TDD測試驅動開發了解一下?

發表于:2023-07-01來源:未知作者:i進擊的攻城獅點擊數: 標簽:tdd測試驅動開發
我第一次接觸TDD這個概念,是在 >中,作者鮑勃大叔在書中,寫了一些關于測試代碼的代碼規范,其實就提到了有關TDD三定律:

1、什么是TDD

我第一次接觸TDD這個概念,是在<<代碼整潔之道>>中,作者鮑勃大叔在書中,寫了一些關于測試代碼的代碼規范,其實就提到了有關TDD三定律:

- 定律一: 在編寫不能通過的單元測試前,不可編寫生產代碼

- 定律二: 只可編寫剛好無法通過的單元測試,不能編譯也算不能通過

- 定律三:只可編寫剛好足以通過當前失敗測試的生存代碼

 

我第一次讀到這三個定律時,不能說是毫無頭緒,只能說是一臉懵逼。

完全不知道作者想表達啥意思,也沒有案例代碼。

對此,我不得不網上查閱的很多相關文章,最后總結出來。

TDD測試驅動開發,就是先寫測試用例,再去開發功能。

這里測試驅動開發里的驅動是做動詞,不是名詞

好了,現在如果別人問你TDD是什么,你就可以直接這樣告訴他。

2、傳統開發方式

我們傳統開發一個功能是這么開發的?

傳統編碼方式

需求分析,想不清楚細節,管他呢,先開始寫

發現需求細節不明確,去跟業務人員確認

確認好幾次終于寫完所有邏輯

運行起來測試一下,靠,果然不工作,調試

調試好久終于工作了

轉測試,QA 測出 bug,debug, 打補丁

終于,代碼可以工作了

一看代碼爛的像坨屎,不敢動,動了還得手工測試,還得讓 QA 測試,還得加班…

傳統的開發方式,都是以開發為主,直接開始編寫代碼,代碼出了問題,再去改,多改幾次,你就會覺得這代碼簡直就是屎山,想重構一下,又怕出新的問題。

 

3、TDD步驟

而TDD測試驅動開發是怎么做的呢?

TDD要求我們先根據需求去拆分任務,把一個大的任務拆分位各個模塊,也就是一個個的函數,我們再去為這些函數去編寫最小的測試,再去寫能讓這個最小的測試通過的最小的實現。

TDD的生命周期圖如下。

這樣做的好處是:

1、有助于我們提前澄清需求

2、可以通過單元測試斷言的診斷機制快速得出反饋

3、當我們寫完了所有的需求,會發現所有的需求都會被測試覆蓋了

 

4、舉個例子

正所謂,光說不練,假把式;下來我們來整個簡單的例子去理解一下測試驅動開發;

假如我需要寫個功能,分析用戶上傳的文本中,每個單詞的數量,并且按照數量倒序排序,這個應該怎么實現:

比如說文本如下:

Hello world
Hello CSDN
Hello Boy
My name is Boy
is is

那輸出就是:

Hello 3
is 3
Boy 2
world 1
CSDN 1
My 1
name 1

 

如果是新手或者是完全不懂代碼設計的人拿到這樣的功能,可能會這樣寫:

public static void main(String[] args) throws Exception{
String words = "";
File file=new File("word.txt");
Scanner sc=new Scanner(file);
while(sc.hasNextLine()){
String line=sc.nextLine();
words = words + line + " ";
}
System.out.println(words);

String[] wordArrays = words.split(" ");

HashMap<String,Integer> hashMap = new HashMap<>();

for(int i=0;i<wordArrays.length;i++){
Set<String> wordSet = hashMap.keySet();
if(wordSet.contains(wordArrays[i])){
Integer number=hashMap.get(wordArrays[i]);
number++;
hashMap.put(wordArrays[i],number);
}else{
hashMap.put(wordArrays[i],1);
}
}
System.out.println("統計單詞------------------");


List<Map.Entry<String, Integer>> list = new ArrayList<Map.Entry<String, Integer>>(hashMap.entrySet()); //轉換為list
list.sort(new Comparator<Map.Entry<String, Integer>>() {
@Override
public int compare(Map.Entry<String, Integer> o1, Map.Entry<String, Integer> o2) {
return o2.getValue().compareTo(o1.getValue());
}
});
System.out.println(list);
}

 

好了,寫完了,讓我們運行一下:

 

 

運行結果貌似也沒有問題,好了提交代碼。

真的沒有問題嗎?統計單詞的數目也沒有問題,但是,如果后期,你要對這段代碼做維護,要去修改這段代碼,這段代碼讀起來是什么感覺?在我看來,這段代碼,就是屎山。

代碼里幾乎完全沒有注釋,讀這段代碼,得從頭開始往下讀,如果其中一段代碼出了問題,你必須在整段代碼中尋找錯誤,非常浪費時間。

讓我們來試試看TDD的寫法,TDD要求首先要把一個功能,去拆分分成各個小功能,然后去為這些小功能寫測試用例。

這個統計單詞數目的代碼應該怎么拆分,試著拆分成小功能一下(這里要注意一下,同樣的功能,在拆分模塊的時候,不同的人選擇的拆分方法可能不同,一千個人里有一千個哈姆雷特,一千個人里也有一千種拆分方法)

 

 

拆分好后,我們就可以為這些功能編寫測試用例了,

我們先編寫測試用例,用assert斷言測試用例是否通過,運行,我們可以看出,方法還沒有進行開發,顯示未通過。

 

這一步,就是TDD定律二中規定的

 

- 定律二: 只可編寫剛好無法通過的單元測試,不能編譯也算不能通過

 

 

下一步要做什么?我們看定律一

 

- 定律一: 在編寫不能通過的單元測試前,不可編寫生產代碼

 

 

定律一反過來是什么意思,不就是編寫好不能通過的單元測試后,就可以開始編寫生產代碼了嗎?

于是開始編寫生產代碼進行測試

在這里,我們編寫好了方法,在執行測試用例后,顯示綠色,代表測試用例通過。

這時候又滿足了第三定律

 

- 定律三:只可編寫剛好足以通過當前失敗測試的生存代碼

 

 

我們的測試用例,專門測試一個小的功能,只為了通過這個方法。

下一步我們再重復以上步驟,去TDD其他模塊。

直到TDD完所有模塊,我們的功能就開發完了。

代碼如下:

public static void main(String[] args) throws Exception {
//讀取文件
File file=new File("word.txt");
String words = readFile(file);
String[] s1 = words.split(" ");
//單詞記錄到hashmap
HashMap<String, Integer> stringIntegerHashMap = groupHashMap(s1);
//排序
List<Map.Entry<String, Integer>> entries = orderHashMap(stringIntegerHashMap);
//輸出
System.out.println(entries);
}

 

方法的代碼太長,太展篇幅就不粘貼了,你看我們新的main方法,代碼就比較簡介,如果出了問題,只可能在這三個方法中其中,我們可以快速定位到方法中去,并且可以用之前編寫的測試用例進行測試。

 

5、總結

關于TDD測試驅動開發,我感覺精髓就是對功能進行拆分,用測試用例去測試功能,我相信很多人,都不會去編寫測試用例,代碼寫好后,就去頁面上點幾下,其實這是不太好的。因為如果這里的功能改動比較頻繁,你每次去頁面上通過點擊的方式測試功能,你得打開瀏覽器,登錄地址,尋找IP,為功能配置參數,這一套下來,真的非常耗費時間。

一次如果5分鐘,10次就是50分鐘。

而TDD建議的是什么?建議通過測試用例的方式去測試,它要求你必須編寫好測試用例后再去寫代碼,這樣就能保住,你每個小功能,都有一個測試用例,這樣,之后你改一個地方,只要找到這個地方所對應的測試用例就能測試了,非常方便。

當然,TDD這種開發方法其實弊端也是很明顯的,比如,大多數程序員,其實是怎么做測試的?就是直接重啟項目,去頁面上看看,功能對不對,測試用例?那是什么?我不是開發嗎,我又不是測試。我去頁面點幾下測試,可能只需要幾分鐘,我去配置測試用例,八成等得二十分鐘,所以大多數程序員可能還是會選擇通過頁面點擊的方式去測試。

測試用例真的是沒有必要的嗎?如果你去新建一個Maven項目,你會發送,test目錄和main目錄是同一級別的

 

 

我相信在設計的時候,可能設計者(設計Maven的程序員肯定是大佬中的大佬),也是認為測試用例是非常重要的,才會把test目錄放在這個位置吧。

原文轉自:http://www.uml.org.cn/Test/202204264.asp

国产97人人超碰caoprom_尤物国产在线一区手机播放_精品国产一区二区三_色天使久久综合给合久久97