<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>

            java程序員如何編寫(xiě)更好的單元測試?

            發(fā)表于:2018-07-17來(lái)源:aliyun作者:HARRIES點(diǎn)擊數: 標簽:單元測試
            在做單元測試時(shí),代碼覆蓋率常常被拿來(lái)作為衡量測試好壞的指標,甚至,用代碼覆蓋率來(lái)考核測試任務(wù)完成情況,比如,代碼覆蓋率必須達到80%或 90%。于是乎,測試人員費盡心思設

            在做單元測試時(shí),代碼覆蓋率常常被拿來(lái)作為衡量測試好壞的指標,甚至,用代碼覆蓋率來(lái)考核測試任務(wù)完成情況,比如,代碼覆蓋率必須達到80%或 90%。于是乎,測試人員費盡心思設計案例覆蓋代碼。用代碼覆蓋率來(lái)衡量,有利也有有弊。本文我們就代碼覆蓋率展開(kāi)討論,也歡迎同學(xué)們踴躍評論。
            首先,讓我們先來(lái)了解一下所謂的“代碼覆蓋率”。我找來(lái)了所謂的定義:

            代碼覆蓋率 = 代碼的覆蓋程度,一種度量方式。

            上面簡(jiǎn)短精悍的文字非常準確的描述了代碼覆蓋率的含義。而代碼覆蓋程度的度量方式是有很多種的,這里介紹一下最常用的幾種:

            1. 語(yǔ)句覆蓋(StatementCoverage)

            又稱(chēng)行覆蓋(LineCoverage),段覆蓋(SegmentCoverage),基本塊覆蓋(BasicBlockCoverage),這是最常用也是最常見(jiàn)的一種覆蓋方式,就是度量被測代碼中每個(gè)可執行語(yǔ)句是否被執行到了。這里說(shuō)的是“可執行語(yǔ)句”,因此就不會(huì )包括像C++的頭文件聲明,代碼注釋?zhuān)招?,等等。非常好理解,只統計能夠執行的代碼被執行了多少行。需要注意的是,單獨一行的花括號{} 也常常被統計進(jìn)去。語(yǔ)句覆蓋常常被人指責為“最弱的覆蓋”,它只管覆蓋代碼中的執行語(yǔ)句,卻不考慮各種分支的組合等等。假如你的上司只要求你達到語(yǔ)句覆蓋,那么你可以省下很多功夫,但是,換來(lái)的確實(shí)測試效果的不明顯,很難更多地發(fā)現代碼中的問(wèn)題。

            這里舉一個(gè)不能再簡(jiǎn)單的例子,我們看下面的被測試代碼:

            int foo(int a, int b)
            {
            return  a / b;
            }
            

            假如我們的測試人員編寫(xiě)如下測試案例:

            TeseCase: a = 10, b = 5
            

            測試人員的測試結果會(huì )告訴你,他的代碼覆蓋率達到了100%,并且所有測試案例都通過(guò)了。然而遺憾的是,我們的語(yǔ)句覆蓋率達到了所謂的100%,但是卻沒(méi)有發(fā)現最簡(jiǎn)單的Bug,比如,當我讓b=0時(shí),會(huì )拋出一個(gè)除零異常。

            正因如此,假如上面只要求測試人員語(yǔ)句覆蓋率達到多少的話(huà),測試人員只要鉆鉆空子,專(zhuān)門(mén)針對如何覆蓋代碼行編寫(xiě)測試案例,就很容易達到主管的要求。當然了,這同時(shí)說(shuō)明了幾個(gè)問(wèn)題:

            1.主管只使用語(yǔ)句覆蓋率來(lái)考核測試人員本身就有問(wèn)題。
            2.測試人員的目的是為了測好代碼,鉆如此的空子是缺乏職業(yè)道德的。
            3.是否應該采用更好的考核方式來(lái)考核測試人員的工作?
            為了尋求更好的考核標準,我們必須先了解完代碼覆蓋率到底還有哪些,如果你的主管只知道語(yǔ)句覆蓋,行覆蓋,那么你應該主動(dòng)向他介紹還有更多的覆蓋方式。比如:

            1. 判定覆蓋(DecisionCoverage)

            又稱(chēng)分支覆蓋(BranchCoverage),所有邊界覆蓋(All-EdgesCoverage),基本路徑覆蓋(BasicPathCoverage),判定路徑覆蓋(Decision-Decision-Path)。它度量程序中每一個(gè)判定的分支是否都被測試到了。這句話(huà)是需要進(jìn)一步理解的,應該非常容易和下面說(shuō)到的條件覆蓋混淆。因此我們直接介紹第三種覆蓋方式,然后和判定覆蓋一起來(lái)對比,就明白兩者是怎么回事了。

            1. 條件覆蓋(ConditionCoverage)

            它度量判定中的每個(gè)子表達式結果true和false是否被測試到了。為了說(shuō)明判定覆蓋和條件覆蓋的區別,我們來(lái)舉一個(gè)例子,假如我們的被測代碼如下:

            int foo(int a, int b)
            {
            if (a < 10 || b < 10) // 判定
            {
            return 0; // 分支一
            }
            else
            {
            return 1; // 分支二
            }
            }
            

            設計判定覆蓋案例時(shí),我們只需要考慮判定結果為true和false兩種情況,因此,我們設計如下的案例就能達到判定覆蓋率100%:

            TestCaes1: a = 5, b = 任意數字  覆蓋了分支一
            TestCaes2: a = 15, b = 15          覆蓋了分支二
            

            設計條件覆蓋案例時(shí),我們需要考慮判定中的每個(gè)條件表達式結果,為了覆蓋率達到100%,我們設計了如下的案例:

            TestCase1: a = 5, b = 5       true,  true
            TestCase4: a = 15, b = 15   false, false
            

            通過(guò)上面的例子,我們應該很清楚了判定覆蓋和條件覆蓋的區別。需要特別注意的是:條件覆蓋不是將判定中的每個(gè)條件表達式的結果進(jìn)行排列組合,而是只要每個(gè)條件表達式的結果true和false測試到了就OK了。因此,我們可以這樣推論:完全的條件覆蓋并不能保證完全的判定覆蓋。比如上面的例子,假如我設計的案例為:

            TestCase1: a = 5, b = 15  true,  false   分支一
            TestCase1: a = 15, b = 5  false, true    分支一
            

            我們看到,雖然我們完整的做到了條件覆蓋,但是我們卻沒(méi)有做到完整的判定覆蓋,我們只覆蓋了分支一。上面的例子也可以看出,這兩種覆蓋方式看起來(lái)似乎都不咋滴。我們接下來(lái)看看第四種覆蓋方式。

            4.路徑覆蓋(PathCoverage)

            又稱(chēng)斷言覆蓋(PredicateCoverage)。它度量了是否函數的每一個(gè)分支都被執行了。 這句話(huà)也非常好理解,就是所有可能的分支都執行一遍,有多個(gè)分支嵌套時(shí),需要對多個(gè)分支進(jìn)行排列組合,可想而知,測試路徑隨著(zhù)分支的數量指數級別增加。比如下面的測試代碼中有兩個(gè)判定分支:

            int foo(int a, int b)
            {
            int nReturn = 0;
            if (a < 10)
            {// 分支一
            nReturn += 1;
            }
            if (b < 10)
            {// 分支二
            nReturn += 10;
            }
            return nReturn;
            }
            

            對上面的代碼,我們分別針對我們前三種覆蓋方式來(lái)設計測試案例:

            1. 語(yǔ)句覆蓋
            TestCase a = 5, b = 5   nReturn = 11
            

            語(yǔ)句覆蓋率100%

            1. 判定覆蓋
            TestCase1 a = 5,   b = 5     nReturn = 11
            
            TestCase2 a = 15, b = 15   nReturn = 0
            

            判定覆蓋率100%

            1. 條件覆蓋
            TestCase1 a = 5,   b = 15   nReturn = 1
            
            TestCase2 a = 15, b = 5     nReturn = 10
            

            條件覆蓋率100%

            我們看到,上面三種覆蓋率結果看起來(lái)都很酷!都達到了100%!主管可能會(huì )非常的開(kāi)心,但是,讓我們再去仔細的看看,上面被測代碼中,nReturn的結果一共有四種可能的返回值:0,1,10,11,而我們上面的針對每種覆蓋率設計的測試案例只覆蓋了部分返回值,因此,可以說(shuō)使用上面任一覆蓋方式,雖然覆蓋率達到了100%,但是并沒(méi)有測試完全。接下來(lái)我們來(lái)看看針對路徑覆蓋設計出來(lái)的測試案例:

            TestCase1 a = 5,    b = 5     nReturn = 0
            
            TestCase2 a = 15,  b = 5     nReturn = 1
            
            TestCase3 a = 5,    b = 15   nReturn = 10
            
            TestCase4 a = 15,  b = 15   nReturn = 11
            

            路徑覆蓋率100%

            太棒了!路徑覆蓋將所有可能的返回值都測試到了。這也正是它被很多人認為是“最強的覆蓋”的原因了。

            還有一些其他的覆蓋方式,如:循環(huán)覆蓋(LoopCoverage),它度量是否對循環(huán)體執行了零次,一次和多余一次循環(huán)。剩下一些其他覆蓋方式就不介紹了。

            總結

            通過(guò)上面的學(xué)習,我們再回頭想想,覆蓋率數據到底有多大意義。我總結了如下幾個(gè)觀(guān)點(diǎn),歡迎大家討論:

            1. 覆蓋率數據只能代表你測試過(guò)哪些代碼,不能代表你是否測試好這些代碼。(比如上面第一個(gè)除零Bug)
            2. 不要過(guò)于相信覆蓋率數據。
            3. 不要只拿語(yǔ)句覆蓋率(行覆蓋率)來(lái)考核你的測試人員。
            4. 路徑覆蓋率 > 判定覆蓋 > 語(yǔ)句覆蓋
            5. 測試人員不能盲目追求代碼覆蓋率,而應該想辦法設計更多更好的案例,哪怕多設計出來(lái)的案例對覆蓋率一點(diǎn)影響也沒(méi)有。

            原文轉自:https://yq.aliyun.com/articles/610512

            ...
            老湿亚洲永久精品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>