日韩黑丝制服一区视频播放|日韩欧美人妻丝袜视频在线观看|九九影院一级蜜桃|亚洲中文在线导航|青草草视频在线观看|婷婷五月色伊人网站|日本一区二区在线|国产AV一二三四区毛片|正在播放久草视频|亚洲色图精品一区

分享

Java單元測(cè)試之JUnit篇

 春和秋榮 2019-05-17

單元測(cè)試是編寫測(cè)試代碼,應(yīng)該準(zhǔn)確、快速地保證程序基本模塊的正確性。
好的單元測(cè)試的標(biāo)準(zhǔn)
JUnit是Java單元測(cè)試框架,已經(jīng)在Eclipse中默認(rèn)安裝。

JUnit4

JUnit4通過注解的方式來識(shí)別測(cè)試方法。目前支持的主要注解有:

  • @BeforeClass 全局只會(huì)執(zhí)行一次,而且是第一個(gè)運(yùn)行
  • @Before 在測(cè)試方法運(yùn)行之前運(yùn)行
  • @Test 測(cè)試方法
  • @After 在測(cè)試方法運(yùn)行之后允許
  • @AfterClass 全局只會(huì)執(zhí)行一次,而且是最后一個(gè)運(yùn)行
  • @Ignore 忽略此方法

下面基于Eclipse介紹JUnit的基本應(yīng)用

基本測(cè)試

  1. 新建一個(gè)項(xiàng)目叫JUnitTest,我們編寫一個(gè)Calculator類,這是一個(gè)能夠簡單實(shí)現(xiàn)加減乘除、平方、開方的計(jì)算器類,然后對(duì)這些功能進(jìn)行單元測(cè)試。
public class Calculator {
    private static int result; // 靜態(tài)變量,用于存儲(chǔ)運(yùn)行結(jié)果
    public void add(int n) {
        result = result + n;
    }
    public void substract(int n) {
        result = result - 1;  //Bug: 正確的應(yīng)該是 result =result-n
    }
    public void multiply(int n) {
    }         // 此方法尚未寫好
    public void divide(int n) {
        result = result / n;
    }
    public void square(int n) {
        result = n * n;
    }
    public void squareRoot(int n) {
        for (; ;) ;            //Bug : 死循環(huán)
    }
    public void clear() {     // 將結(jié)果清零
        result = 0;
    }
    public int getResult(){
        return result;
    }
}
  1. 將JUnit4單元測(cè)試包引入這個(gè)項(xiàng)目:在該項(xiàng)目上點(diǎn)右鍵,點(diǎn)“屬性”,如圖

    在彈出的屬性窗口中,首先在左邊選擇“Java Build Path”,然后到右上選擇“Libraries”標(biāo)簽,之后在最右邊點(diǎn)擊“Add Library…”按鈕,如下圖所示



    然后在新彈出的對(duì)話框中選擇JUnit4并點(diǎn)擊確定,如上圖所示,JUnit4軟件包就被包含進(jìn)我們這個(gè)項(xiàng)目了。
  2. 生成JUnit測(cè)試框架:在Eclipse的Package Explorer中用右鍵點(diǎn)擊該類彈出菜單,選擇“New JUnit Test Case”。如下圖所示:



    點(diǎn)擊“下一步”后,系統(tǒng)會(huì)自動(dòng)列出你這個(gè)類中包含的方法,選擇你要進(jìn)行測(cè)試的方法。此例中,我們僅對(duì)“加、減、乘、除”四個(gè)方法進(jìn)行測(cè)試。

    之后系統(tǒng)會(huì)自動(dòng)生成一個(gè)新類CalculatorTest,里面包含一些空的測(cè)試用例。你只需要將這些測(cè)試用例稍作修改即可使用。
    完整的CalculatorTest代碼如下:
public class CalculatorTest {   
    private static Calculator calculator = new Calculator();

    @Before
    public void setUp() throws Exception {
        calculator.clear();
    }

    @Test
    public void testAdd() {
        calculator.add(3);
        calculator.add(4);
        assertEquals(7, calculator.getResult());

    }

    @Test
    public void testSubstract() {
        calculator.add(8);
        calculator.substract(3);
        assertEquals(5, calculator.getResult());

    }

    @Ignore("Multiply() Not yet implemented")
    @Test
    public void testMultiply() {
        fail("Not yet implemented");
    }

    @Test
    public void testDivide() {
        calculator.add(8);
        calculator.divide(2);
        assertEquals(4, calculator.getResult());

    }

}
  1. 運(yùn)行測(cè)試代碼:按照上述代碼修改完畢后,我們?cè)贑alculatorTest類上點(diǎn)右鍵,選擇“Run As a JUnit Test”來運(yùn)行我們的測(cè)試,如下圖所示

    運(yùn)行結(jié)果如下:

    進(jìn)度條是紅顏色表示發(fā)現(xiàn)錯(cuò)誤,具體的測(cè)試結(jié)果在進(jìn)度條上面有表示“共進(jìn)行了4個(gè)測(cè)試,其中1個(gè)測(cè)試被忽略,一個(gè)測(cè)試失敗”。
    限時(shí)測(cè)試
    對(duì)于那些邏輯很復(fù)雜,循環(huán)嵌套比較深的程序,很有可能出現(xiàn)死循環(huán),因此一定要采取一些預(yù)防措施。限時(shí)測(cè)試是一個(gè)很好的解決方案。我們給這些測(cè)試函數(shù)設(shè)定一個(gè)執(zhí)行時(shí)間,超過了這個(gè)時(shí)間,他們就會(huì)被系統(tǒng)強(qiáng)行終止,并且系統(tǒng)還會(huì)向你匯報(bào)該函數(shù)結(jié)束的原因是因?yàn)槌瑫r(shí),這樣你就可以發(fā)現(xiàn)這些Bug了。要實(shí)現(xiàn)這一功能,只需要給@Test標(biāo)注加一個(gè)參數(shù)即可,代碼如下:
    @Test(timeout = 1000)
    public void squareRoot() {
        calculator.squareRoot(4);
        assertEquals(2, calculator.getResult());
    }

Timeout參數(shù)表明了你要設(shè)定的時(shí)間,單位為毫秒,因此1000就代表1秒。


測(cè)試異常

JAVA中的異常處理也是一個(gè)重點(diǎn),因此你經(jīng)常會(huì)編寫一些需要拋出異常的函數(shù)。那么,如果你覺得一個(gè)函數(shù)應(yīng)該拋出異常,但是它沒拋出,這算不算Bug呢?這當(dāng)然是Bug,并JUnit也考慮到了這一點(diǎn),來幫助我們找到這種Bug。例如,我們寫的計(jì)算器類有除法功能,如果除數(shù)是一個(gè)0,那么必然要拋出“除0異?!薄R虼?,我們很有必要對(duì)這些進(jìn)行測(cè)試。代碼如下:

  @Test(expected = ArithmeticException.class)
  public void divideByZero(){
        calculator.divide(0);
   }

如上述代碼所示,我們需要使用@Test標(biāo)注的expected屬性,將我們要檢驗(yàn)的異常傳遞給他,這樣JUnit框架就能自動(dòng)幫我們檢測(cè)是否拋出了我們指定的異常。
參數(shù)化測(cè)試
我們可能遇到過這樣的函數(shù),它的參數(shù)有許多特殊值,或者說他的參數(shù)分為很多個(gè)區(qū)域。
例如,測(cè)試一下“計(jì)算一個(gè)數(shù)的平方”這個(gè)函數(shù),暫且分三類:正數(shù)、0、負(fù)數(shù)。在編寫測(cè)試的時(shí)候,至少要寫3個(gè)測(cè)試,把這3種情況都包含了,這確實(shí)是一件很麻煩的事情。測(cè)試代碼如下:

    public class AdvancedTest { 
        private static Calculator calculator = new Calculator();
        @Before
        public void clearCalculator(){
            calculator.clear();
        }

        @Test
        public void square1() {
            calculator.square(2);
            assertEquals(4, calculator.getResult());
        }     

        @Test    
        public void square2(){
            calculator.square(0);
            assertEquals(0, calculator.getResult());
        }

        @Test    
        public void square3(){
            calculator.square(-3);
            assertEquals(9, calculator.getResult());
        }
     }

為了簡化類似的測(cè)試,JUnit4提出了“參數(shù)化測(cè)試”的概念,只寫一個(gè)測(cè)試函數(shù),把這若干種情況作為參數(shù)傳遞進(jìn)去,一次性的完成測(cè)試。代碼如下:

    @RunWith(Parameterized.class)
    public class SquareTest{
        private static Calculator calculator = new Calculator();
        private int param;
        private int result;     

    @Parameters    
    public static Collection data() {
        return Arrays.asList(new Object[][]{
               {2, 4},
               {0, 0},
               {-3, 9},
        });
    }

    //構(gòu)造函數(shù),對(duì)變量進(jìn)行初始化
    public SquareTest(int param, int result){
        this.param = param;
            this.result = result;
    }

    @Test    
    public void square(){
        calculator.square(param);
        assertEquals(result, calculator.getResult());
    }
 }

執(zhí)行了3次該測(cè)試類,依次采用了數(shù)據(jù)集合中的數(shù)據(jù){處理值,預(yù)期處理結(jié)果},結(jié)果如下:

代碼分析如下:

  • 為這種測(cè)試專門生成一個(gè)新的類,而不能與其他測(cè)試共用同一個(gè)類,此例中我們定義了一個(gè)SquareTest類。
  • 為這個(gè)類指定一個(gè)Runner,而不能使用默認(rèn)的Runner,@RunWith(Parameterized.class)這條語句就是為這個(gè)類指定了一個(gè)ParameterizedRunner
  • 定義一個(gè)待測(cè)試的類,并且定義兩個(gè)變量,一個(gè)用于存放參數(shù),一個(gè)用于存放期待的結(jié)果。
  • 定義測(cè)試數(shù)據(jù)的集合,也就是上述的data()方法,該方法可以任意命名,但是必須使用@Parameters標(biāo)注進(jìn)行修飾。
  • 定義構(gòu)造函數(shù),其功能就是對(duì)先前定義的兩個(gè)參數(shù)進(jìn)行初始化

    本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊一鍵舉報(bào)。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評(píng)論

    發(fā)表

    請(qǐng)遵守用戶 評(píng)論公約

    類似文章 更多