<ruby id="h6500"><table id="h6500"></table></ruby>
    1. <ruby id="h6500"><video id="h6500"></video></ruby>
          1. <progress id="h6500"><u id="h6500"><form id="h6500"></form></u></progress>

            先測試再開(kāi)發(fā)?TDD測試驅動(dòng)開(kāi)發(fā)了解一下?

            發(fā)表于:2023-07-01來(lái)源:未知作者:i進(jìn)擊的攻城獅點(diǎn)擊數: 標簽:tdd測試驅動(dòng)開(kāi)發(fā)
            我第一次接觸TDD這個(gè)概念,是在 >中,作者鮑勃大叔在書(shū)中,寫(xiě)了一些關(guān)于測試代碼的代碼規范,其實(shí)就提到了有關(guān)TDD三定律:

            1、什么是TDD

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

            - 定律一: 在編寫(xiě)不能通過(guò)的單元測試前,不可編寫(xiě)生產(chǎn)代碼

            - 定律二: 只可編寫(xiě)剛好無(wú)法通過(guò)的單元測試,不能編譯也算不能通過(guò)

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

             

            我第一次讀到這三個(gè)定律時(shí),不能說(shuō)是毫無(wú)頭緒,只能說(shuō)是一臉懵逼。

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

            對此,我不得不網(wǎng)上查閱的很多相關(guān)文章,最后總結出來(lái)。

            TDD測試驅動(dòng)開(kāi)發(fā),就是先寫(xiě)測試用例,再去開(kāi)發(fā)功能。

            這里測試驅動(dòng)開(kāi)發(fā)里的驅動(dòng)是做動(dòng)詞,不是名詞

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

            2、傳統開(kāi)發(fā)方式

            我們傳統開(kāi)發(fā)一個(gè)功能是這么開(kāi)發(fā)的?

            傳統編碼方式

            需求分析,想不清楚細節,管他呢,先開(kāi)始寫(xiě)

            發(fā)現需求細節不明確,去跟業(yè)務(wù)人員確認

            確認好幾次終于寫(xiě)完所有邏輯

            運行起來(lái)測試一下,靠,果然不工作,調試

            調試好久終于工作了

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

            終于,代碼可以工作了

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

            傳統的開(kāi)發(fā)方式,都是以開(kāi)發(fā)為主,直接開(kāi)始編寫(xiě)代碼,代碼出了問(wèn)題,再去改,多改幾次,你就會(huì )覺(jué)得這代碼簡(jiǎn)直就是屎山,想重構一下,又怕出新的問(wèn)題。

             

            3、TDD步驟

            而TDD測試驅動(dòng)開(kāi)發(fā)是怎么做的呢?

            TDD要求我們先根據需求去拆分任務(wù),把一個(gè)大的任務(wù)拆分位各個(gè)模塊,也就是一個(gè)個(gè)的函數,我們再去為這些函數去編寫(xiě)最小的測試,再去寫(xiě)能讓這個(gè)最小的測試通過(guò)的最小的實(shí)現。

            TDD的生命周期圖如下。

            這樣做的好處是:

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

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

            3、當我們寫(xiě)完了所有的需求,會(huì )發(fā)現所有的需求都會(huì )被測試覆蓋了

             

            4、舉個(gè)例子

            正所謂,光說(shuō)不練,假把式;下來(lái)我們來(lái)整個(gè)簡(jiǎn)單的例子去理解一下測試驅動(dòng)開(kāi)發(fā);

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

            比如說(shuō)文本如下:

            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

             

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

            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);
            }

             

            好了,寫(xiě)完了,讓我們運行一下:

             

             

            運行結果貌似也沒(méi)有問(wèn)題,好了提交代碼。

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

            代碼里幾乎完全沒(méi)有注釋?zhuān)x這段代碼,得從頭開(kāi)始往下讀,如果其中一段代碼出了問(wèn)題,你必須在整段代碼中尋找錯誤,非常浪費時(shí)間。

            讓我們來(lái)試試看TDD的寫(xiě)法,TDD要求首先要把一個(gè)功能,去拆分分成各個(gè)小功能,然后去為這些小功能寫(xiě)測試用例。

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

             

             

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

            我們先編寫(xiě)測試用例,用assert斷言測試用例是否通過(guò),運行,我們可以看出,方法還沒(méi)有進(jìn)行開(kāi)發(fā),顯示未通過(guò)。

             

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

             

            - 定律二: 只可編寫(xiě)剛好無(wú)法通過(guò)的單元測試,不能編譯也算不能通過(guò)

             

             

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

             

            - 定律一: 在編寫(xiě)不能通過(guò)的單元測試前,不可編寫(xiě)生產(chǎn)代碼

             

             

            定律一反過(guò)來(lái)是什么意思,不就是編寫(xiě)好不能通過(guò)的單元測試后,就可以開(kāi)始編寫(xiě)生產(chǎn)代碼了嗎?

            于是開(kāi)始編寫(xiě)生產(chǎn)代碼進(jìn)行測試

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

            這時(shí)候又滿(mǎn)足了第三定律

             

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

             

             

            我們的測試用例,專(zhuān)門(mén)測試一個(gè)小的功能,只為了通過(guò)這個(gè)方法。

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

            直到TDD完所有模塊,我們的功能就開(kāi)發(fā)完了。

            代碼如下:

            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);
            }

             

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

             

            5、總結

            關(guān)于TDD測試驅動(dòng)開(kāi)發(fā),我感覺(jué)精髓就是對功能進(jìn)行拆分,用測試用例去測試功能,我相信很多人,都不會(huì )去編寫(xiě)測試用例,代碼寫(xiě)好后,就去頁(yè)面上點(diǎn)幾下,其實(shí)這是不太好的。因為如果這里的功能改動(dòng)比較頻繁,你每次去頁(yè)面上通過(guò)點(diǎn)擊的方式測試功能,你得打開(kāi)瀏覽器,登錄地址,尋找IP,為功能配置參數,這一套下來(lái),真的非常耗費時(shí)間。

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

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

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

            測試用例真的是沒(méi)有必要的嗎?如果你去新建一個(gè)Maven項目,你會(huì )發(fā)送,test目錄和main目錄是同一級別的

             

             

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

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

            ...
            老湿亚洲永久精品ww47香蕉图片_日韩欧美中文字幕北美法律_国产AV永久无码天堂影院_久久婷婷综合色丁香五月
              <ruby id="h6500"><table id="h6500"></table></ruby>
              1. <ruby id="h6500"><video id="h6500"></video></ruby>
                    1. <progress id="h6500"><u id="h6500"><form id="h6500"></form></u></progress>