看過我前面的那篇初體驗的就會發現一個問題,咱們的測試代碼大量的重複了。在這裏先貼出原來的那2篇代碼:java
測試源碼:數據庫
package test.junit4test; import java.util.regex.Matcher; import java.util.regex.Pattern; public final class Linkin { /** * @建立時間: 2016年1月28日 * @相關參數: @param name * @相關參數: @return * @功能描述:格式化一個Java駝峯規則的字符串成數據庫規則。 */ public static final String underscoreName(String name) { if (name == null) { return null; } if ("".equals(name)) { return ""; } StringBuilder result = new StringBuilder().append(name.substring(0, 1).toLowerCase()); for (int i = 1; i < name.length() - 1; i++) { String s = name.substring(i, i + 1); String slc = s.toLowerCase(); String pres = name.substring(i - 1, i); String preslc = pres.toLowerCase(); if (!s.equals(slc) && pres.equals(preslc)) { result.append("_").append(slc); } else { result.append(slc); } } return result.append(name.substring(name.length() - 1, name.length()).toLowerCase()).toString(); } /** * @建立時間: 2016年1月28日 * @相關參數: @param name Java對象名稱 * @相關參數: @return 格式化後的名稱 * @功能描述: 將Java對象名稱(每一個單詞的頭字母大寫)按照數據庫命名的習慣進行格式化 * <p> * 格式化後的數據爲小寫字母,而且使用下劃線分割命名單詞。 * 若是參數name爲null,則返回null。 * 例如:employeeInfo 通過格式化以後變爲 employee_info * </p> */ public static final String wordFormat4DB(String name) { if (name == null) { return null; } Pattern p = Pattern.compile("[A-Z]"); Matcher m = p.matcher(name); StringBuffer sb = new StringBuffer(); while (m.find()) { if (m.start() != 0) { m.appendReplacement(sb, ("_" + m.group()).toLowerCase()); } } return m.appendTail(sb).toString().toLowerCase(); } }
測試代碼:數組
package test.junit4test; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNull; import org.junit.Before; import org.junit.Test; public class LinkinTest { private static final String JAVANAME = "userInfo"; private static final String DBNAME = "user_info"; Linkin linkin = null; @Before public void setUp() { linkin = new Linkin(); } @Test // 測試字符串正常的狀況 public void testUnderScoreName4Normal() { String underscoreName = linkin.underscoreName(JAVANAME); assertEquals(DBNAME, underscoreName); } @Test // 測試字符串爲null的狀況 public void testUnderScoreName4Null() { String underscoreName = linkin.underscoreName(null); assertNull(underscoreName); } @Test // 測試字符串爲空字符串的狀況 public void testUnderScoreName4Empty() { String underscoreName = linkin.underscoreName(""); assertEquals("", underscoreName); } @Test // 測試當首字母大寫時的狀況 public void testUnderScoreName4Begin() { String underscoreName = linkin.underscoreName("UserInfo"); assertEquals(DBNAME, underscoreName); } @Test // 測試當尾字母爲大寫時的狀況 public void testUnderScoreName4End() { String underscoreName = linkin.underscoreName("userInfO"); assertEquals(DBNAME, underscoreName); } @Test // 測試多個相連字母大寫時的狀況 public void testUnderScoreName4Together() { String underscoreName = linkin.underscoreName("userINfo"); assertEquals(DBNAME, underscoreName); } }
爲了保證單元測試的嚴謹性,咱們模擬了不一樣類型的字符串來測試方法的處理能力,爲此咱們編寫大量的單元測試方法。但是這些測試方法都是大同小異:代碼結構都是相同的,不一樣的僅僅是測試數據和指望值。有沒有更好的方法將測試方法中相同app
的代碼結構提取出來,提升代碼的重用度,減小複製粘貼代碼的煩惱?在之前的 JUnit 版本上,並無好的解決方法,而如今您可使用 JUnit 提供的參數化測試方式應對這個問題。函數
2,爲測試類聲明幾個變量,分別用於存放指望值和測試所用數據。單元測試
3,爲測試類聲明一個使用註解 org.junit.runners.Parameterized.Parameters 修飾的,返回值爲 java.util.Collection 的公共靜態方法,並在此方法中初始化全部須要測試的參數對。測試
4,爲測試類聲明一個帶有參數的公共構造函數,並在其中爲第二個環節中聲明的幾個變量賦值。ui
5,編寫測試方法,使用定義的變量做爲參數進行測試。this
package test.junit4test; import java.util.Arrays; import java.util.Collection; import org.junit.Assert; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.Parameterized; import org.junit.runners.Parameterized.Parameters; @RunWith(Parameterized.class) public class LinkinTest { private String expected; private String target; @Parameters public static Collection<String[]> words() { return Arrays.asList(new String[][] { { "employee_info", "employeeInfo" }, // 測試通常的處理狀況 { null, null }, // 測試 null 時的處理狀況 { "", "" }, // 測試空字符串時的處理狀況 { "employee_info", "EmployeeInfo" }, // 測試當首字母大寫時的狀況 { "employee_info_a", "employeeInfoA" }, // 測試當尾字母爲大寫時的狀況 { "employee_a_info", "employeeAInfo" }// 測試多個相連字母大寫時的狀況 }); } /** * @建立時間: 2016年1月28日 * @相關參數: @param expected 指望的測試結果,對應參數集中的第一個參數 * @相關參數: @param target 測試數據,對應參數集中的第二個參數 * @構造描述: 參數化測試必須的構造函數 */ public LinkinTest(String expected, String target) { this.expected = expected; this.target = target; } /** * 測試將 Java 對象名稱到數據庫名稱的轉換 */ @Test public void wordFormat4DB() { Assert.assertEquals(expected, Linkin.wordFormat4DB(target)); } }
很明顯,代碼瘦身了。在靜態方法 words 中,咱們使用二維數組來構建測試所須要的參數列表,其中每一個數組中的元素的放置順序並無什麼要求,只要和構造函數中的順序保持一致就能夠了。如今若是再增長一種測試狀況,只須要在靜態方法 words 中添加相應的數組便可,再也不須要複製粘貼出一個新的方法出來了。運行上面的測試,將會根據@Parameters註解修飾的方法返回一個Collection,而後進行相同次數的循環。編碼
如今咱們來逐步分析下parameters這隻小怪獸在junit中的運行過程,以理解這份強大的功能:
1,首先junit調用了靜態方法words,而後junit爲words這個集合中的每一個數組進行循環。
2,junit調用惟一的構造器,注意這個時候,若是該測試類存在多個構造器,junit就會拋出一個斷言錯誤。
3,junit使用由該數組參數構成的一系列參數來調用構造器,而後開始一次測試。
4,重複上面的步驟,直到都運行完Collection集合中的數組元素。
junit的parameterized類是junit衆多測試運行器的一個。測試運行器可讓你控制junit如何運行測試。咱們可使用別的運行器,也能夠自定義本身的運行器來使用,使用RunWith就能夠。下一篇咱們就來整理下junit運行器。