zoukankan      html  css  js  c++  java
  • junit参数化测试

    在前面的junit4初体验中我就说过,junit参数化测试是一只小怪兽,只逼编码痛点,现在我们这里来整理一下。

    看过我前面的那篇初体验的就会发现一个问题,我们的测试代码大量的重复了。在这里先贴出原来的那2篇代码:

    测试源码:

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

    为了保证单元测试的严谨性,我们模拟了不同类型的字符串来测试方法的处理能力,为此我们编写大量的单元测试方法。可是这些测试方法都是大同小异:代码结构都是相同的,不同的仅仅是测试数据和期望值。有没有更好的方法将测试方法中相同

    的代码结构提取出来,提高代码的重用度,减少复制粘贴代码的烦恼?在以前的 JUnit 版本上,并没有好的解决方法,而现在您可以使用 JUnit 提供的参数化测试方式应对这个问题。


    参数化测试的编写稍微有点麻烦(当然这是相对于 JUnit 中其它特性而言):
    1,为准备使用参数化测试的测试类指定特殊的运行器 org.junit.runners.Parameterized。

    2,为测试类声明几个变量,分别用于存放期望值和测试所用数据。

    3,为测试类声明一个使用注解 org.junit.runners.Parameterized.Parameters 修饰的,返回值为 java.util.Collection 的公共静态方法,并在此方法中初始化所有需要测试的参数对。

    4,为测试类声明一个带有参数的公共构造函数,并在其中为第二个环节中声明的几个变量赋值。

    5,编写测试方法,使用定义的变量作为参数进行测试。


    我们按照这个标准,重新改造一番我们的单元测试代码:
    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运行器。

  • 相关阅读:
    Oracle11g远程连接配置 visual studio 2003
    窗体设计器的使用套件
    Visual Studio 2003“无法启动调试 没有正确安装调试器“请修复调试器的解决办法
    eclipse maven插件安装教程
    遇到错误ERROR 1044 (42000): Access denied for user ''@'localhost'to database 'mysql',的解决办法
    定位
    盒子模型
    CSS3美化网页元素
    CSS随笔
    前端基础随笔
  • 原文地址:https://www.cnblogs.com/LinkinPark/p/5232888.html
Copyright © 2011-2022 走看看