2013年1月29日 星期二

Data Driven Testing by JUnit Parameterized Tests

本文直接展示兩種unit test的寫法來比較JUnit Parameterized Tests的好處在哪。

首先是傳統的寫法:
UnifiedBusinessNumberValidatorTest
package com.gss.gmo.cao.validator.constraints.impl;

import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;

import org.junit.Test;

public class UnifiedBusinessNumberValidatorTest {

    @Test
    public void testIsValid() {
        UnifiedBusinessNumberValidator unifiedBusinessNumberValidator = new UnifiedBusinessNumberValidator();
        assertTrue(unifiedBusinessNumberValidator.isValid(null, null));
        assertFalse(unifiedBusinessNumberValidator.isValid("", null));
        assertFalse(unifiedBusinessNumberValidator.isValid("12345678", null));
        assertTrue(unifiedBusinessNumberValidator.isValid("00651474", null));
        assertFalse(unifiedBusinessNumberValidator.isValid("00651479", null));
        assertTrue(unifiedBusinessNumberValidator.isValid("22425662", null));
        assertFalse(unifiedBusinessNumberValidator.isValid("22425669", null));
        assertTrue(unifiedBusinessNumberValidator.isValid("28706210", null));
        assertTrue(unifiedBusinessNumberValidator.isValid("53112454", null));
        assertTrue(unifiedBusinessNumberValidator.isValid("04607774", null));
        assertTrue(unifiedBusinessNumberValidator.isValid("22446771", null));
        assertTrue(unifiedBusinessNumberValidator.isValid("22515072", null));
        assertTrue(unifiedBusinessNumberValidator.isValid("22595770", null));
        assertTrue(unifiedBusinessNumberValidator.isValid("22227375", null));
        assertTrue(unifiedBusinessNumberValidator.isValid("07006628", null));
    }

}
執行結果:

接下來我們利用JUnit Parameterized Tests的寫法改寫一次這個unit test:
UnifiedBusinessNumberValidatorParameterizedTest
package com.gss.gmo.cao.validator.constraints.impl;

import static org.junit.Assert.assertEquals;

import java.util.ArrayList;
import java.util.Collection;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import org.junit.runners.Parameterized.Parameters;

/**
 * @author linus_chien
 *
 */
@RunWith(value = Parameterized.class)
public class UnifiedBusinessNumberValidatorParameterizedTest {

    @Parameters(name = "[{index}]: [{1}] is valid? [{0}]")
    public static Collection<Object[]> data() {
        Collection<Object[]> data = new ArrayList<Object[]>();
        data.add(new Object[] { Boolean.TRUE, null });
        data.add(new Object[] { Boolean.FALSE, "" });
        data.add(new Object[] { Boolean.FALSE, "12345678" });
        data.add(new Object[] { Boolean.TRUE, "00651474" });
        data.add(new Object[] { Boolean.FALSE, "00651479" });
        data.add(new Object[] { Boolean.TRUE, "22425662" });
        data.add(new Object[] { Boolean.FALSE, "22425669" });
        data.add(new Object[] { Boolean.TRUE, "28706210" });
        data.add(new Object[] { Boolean.TRUE, "53112454" });
        data.add(new Object[] { Boolean.TRUE, "04607774" });
        data.add(new Object[] { Boolean.TRUE, "22446771" });
        data.add(new Object[] { Boolean.TRUE, "22515072" });
        data.add(new Object[] { Boolean.TRUE, "22595770" });
        data.add(new Object[] { Boolean.TRUE, "22227375" });
        data.add(new Object[] { Boolean.TRUE, "07006628" });
        return data;
    }

    private final boolean result;

    private final String unifiedBusinessNumber;

    public UnifiedBusinessNumberValidatorParameterizedTest(Boolean result, String unifiedBusinessNumber) {
        this.result = result;
        this.unifiedBusinessNumber = unifiedBusinessNumber;
    }

    @Test
    public void test() {
        UnifiedBusinessNumberValidator unifiedBusinessNumberValidator = new UnifiedBusinessNumberValidator();
        assertEquals(result, unifiedBusinessNumberValidator.isValid(unifiedBusinessNumber, null));
    }

}
執行結果:

從執行結果我們可以發現每一筆資料都變成一個test case,而且可以從名稱上了解測試資料內容,這樣在test case failed的時候可以很清楚知道是哪筆資料出錯,從報表上就可以一目瞭然。

須注意的是@Parameters可以下name attribute是4.11版之後才支援。