zoukankan      html  css  js  c++  java
  • junit4初体验

    OK,现在我们正式开始junit4系列的整理。前面的junit38作为4的补充知道就好了,实际编码中我们以4为主。这里先来一把junit的初体验,同时也让我们来一步一步的了解下TDD的好处。

    ORM大家肯定熟悉的不能再熟悉了,大Java面向对象编码,但是数据库存的是表结构,所以我们不可避免的就要来做ORM映射。其中关键的一步就是将Java对象映射成数据库中的表,将一个Java对象的属性映射成数据库一个表的一个字段。

    在这里我们就写一个工具类,将Java对象名称按照数据库命名的习惯来进行格式化。假如我们现在还没有任何的测试,一般的TDD中都是测试先行,先写个测试方法,因为没有任何的测试源代码,所以这个时候测试方法中要fail出去一个异常。然后人工去实现测试然后接着测试。在这里我们就不用先写那个失败的测试方法了,我们这里直接编码一个方法来实现刚才那个功能。

    代码如下:

    public String underscoreName(String name)
    	{
    		StringBuilder result = new StringBuilder();
    		result.append(name.substring(0, 1).toLowerCase());
    		for (int i = 1; i < name.length(); i++)
    		{
    			String s = name.substring(i, i + 1);
    			String slc = s.toLowerCase();
    			if (!s.equals(slc))
    			{
    				result.append("_").append(slc);
    			}
    			else
    			{
    				result.append(s);
    			}
    		}
    		return result.toString();
    	}
    OK,现在方法写好了,那我们开始写测试。

    @Test
    	public void testUnderScoreName4Normal()
    	{
    		Linkin linkin = new Linkin();
    		String underscoreName = linkin.underscoreName("userInfo");
    		assertEquals("user_info", underscoreName);
    	}


    OK,写的这个测试用例通过了,那是不是就万事大吉了呢?NO,NO,NO,现在就宣布代码通过了单元测试还为时过早。我们应该记住:单元测试代码不是用来证明我是对的,而是为了证明我没有错。 因此单元测试的范围要全面,比如对边界值、正常值、错误值得测试;对代码可能出现的问题要全面预测,而这也正是需求分析、详细设计环节中要考虑的。显然, 我们的测试才刚刚开始,继续补充一些对特殊情况的测试。

    OK,现在我们来写相关测试:

    package test.junit4test;
    
    import static org.junit.Assert.assertEquals;
    import static org.junit.Assert.assertNull;
    
    import org.junit.Test;
    
    public class LinkinTest
    {
    
    	@Test
    	// 测试字符串正常的情况
    	public void testUnderScoreName4Normal()
    	{
    		Linkin linkin = new Linkin();
    		String underscoreName = linkin.underscoreName("userInfo");
    		assertEquals("user_info", underscoreName);
    	}
    
    	@Test
    	// 测试字符串为null的情况
    	public void testUnderScoreName4Null()
    	{
    		Linkin linkin = new Linkin();
    		String underscoreName = linkin.underscoreName(null);
    		assertNull(underscoreName);
    	}
    
    	@Test
    	// 测试字符串为空字符串的情况
    	public void testUnderScoreName4Empty()
    	{
    		Linkin linkin = new Linkin();
    		String underscoreName = linkin.underscoreName("");
    		assertEquals("", underscoreName);
    	}
    
    	@Test
    	// 测试当首字母大写时的情况
    	public void testUnderScoreName4Begin()
    	{
    		Linkin linkin = new Linkin();
    		String underscoreName = linkin.underscoreName("UserInfo");
    		assertEquals("user_info", underscoreName);
    	}
    
    	@Test
    	// 测试当尾字母为大写时的情况
    	public void testUnderScoreName4End()
    	{
    		Linkin linkin = new Linkin();
    		String underscoreName = linkin.underscoreName("userInfO");
    		assertEquals("user_info", underscoreName);
    	}
    
    	@Test
    	// 测试多个相连字母大写时的情况
    	public void testUnderScoreName4Together()
    	{
    		Linkin linkin = new Linkin();
    		String underscoreName = linkin.underscoreName("userINfo");
    		assertEquals("user_info", underscoreName);
    	}
    
    }
    
    测试代码写好以后,运行结果如下:



    忽忽,蛋疼的情况出现了,2个错误,2个失败,好吧,说明我们的代码问题还是挺多的呢。开始改吧。

    public 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();
    	}
    OK,现在测试全部通过了,现在是不是万事大吉了呢?NO,NO,NO,代码写的太糙了,只是为了我们测试通过,现在我们修改自己的测试代码,让代码更加漂亮点。

    修改后的测试代码如下:

    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);
    	}
    
    }
    
    原来的被测试源码如下:

    package test.junit4test;
    
    import java.util.regex.Matcher;
    import java.util.regex.Pattern;
    
    public class Linkin
    {
    
    	/**
    	 * @创建时间: 2016年1月28日
    	 * @相关参数: @param name
    	 * @相关参数: @return
    	 * @功能描述:格式化一个Java驼峰规则的字符串成数据库规则。
    	 */
    	public 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 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();
    	}
    
    }
    
    上面的这段代码有2个方法,第一个方法我是从spring-jdbc-template中复制出来,但是很遗憾并没有严格的通过我自己写的单元测试。下面的代码我自己写的,也实现了类似的功能。如果感兴趣,可以自行补上测试。


    总结:

    1,JUnit 将测试失败的情况分为两种:failure 和 error。Failure 一般由单元测试使用的断言方法判断失败引起,它表示在测试点发现了问题;而 error 则是由代码异常引起,这是测试目的之外的发现,它可能产生于测试代码本身的错误(测试代码也

    是代码,同样无法保证完全没有缺陷),也可能是被测试代码中的 一个隐藏的bug。

    2,再次强调,单元测试只能保证你的代码没有错,但是不能保证你的代码是对的。异常测试是一个很重要的很重要的一部分,一定不能忽略这部分测试。

    3,及时的重构源代码,有单元测试在不怕重构没法测试,重构对于自己的源码的结构和设计都会是越来越好,比如什么高内聚,低耦合,比如什么单一职责,比如取消重复等等。

    4,及时的维护测试代码,测试代码也是代码,也需要我们维护,这样很方便我们向后兼容迭代代码。比如说上面的测试类,我们写了大量的重复,每次都是传入1个字符串然后去比较我们的预期和实际,在后面的系列中我会讲到一只小怪兽,Parameterized这个后面再说。


    junit4初体验就先体验到这里,下一篇我会重点整理下junit4的几个常用的注解和使用。

  • 相关阅读:
    long和Long的区别
    C语言的变量的内存分配
    Java蓝桥杯 算法提高 九宫格
    Java实现 蓝桥杯算法提高金明的预算方案
    Java实现 蓝桥杯 算法提高 新建Microsoft world文档
    Java实现 蓝桥杯 算法提高 快乐司机
    Java实现 蓝桥杯 算法提高 三角形
    Java实现 蓝桥杯 算法提高 三角形
    Java实现 蓝桥杯 算法提高 三角形
    Java实现 蓝桥杯 算法提高 三角形
  • 原文地址:https://www.cnblogs.com/LinkinPark/p/5232891.html
Copyright © 2011-2022 走看看