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的几个常用的注解和使用。

junit4初体验的更多相关文章

  1. Spring之初体验

                                     Spring之初体验 Spring是一个轻量级的Java Web开发框架,以IoC(Inverse of Control 控制反转)和 ...

  2. .NET平台开源项目速览(15)文档数据库RavenDB-介绍与初体验

    不知不觉,“.NET平台开源项目速览“系列文章已经15篇了,每一篇都非常受欢迎,可能技术水平不高,但足够入门了.虽然工作很忙,但还是会抽空把自己知道的,已经平时遇到的好的开源项目分享出来.今天就给大家 ...

  3. Xamarin+Prism开发详解四:简单Mac OS 虚拟机安装方法与Visual Studio for Mac 初体验

    Mac OS 虚拟机安装方法 最近把自己的电脑升级了一下SSD固态硬盘,总算是有容量安装Mac 虚拟机了!经过心碎的安装探索,尝试了国内外的各种安装方法,最后在youtube上找到了一个好方法. 简单 ...

  4. Xamarin.iOS开发初体验

    aaarticlea/png;base64,iVBORw0KGgoAAAANSUhEUgAAAKwAAAA+CAIAAAA5/WfHAAAJrklEQVR4nO2c/VdTRxrH+wfdU84pW0

  5. 【腾讯Bugly干货分享】基于 Webpack & Vue & Vue-Router 的 SPA 初体验

    本文来自于腾讯bugly开发者社区,非经作者同意,请勿转载,原文地址:http://dev.qq.com/topic/57d13a57132ff21c38110186 导语 最近这几年的前端圈子,由于 ...

  6. 【Knockout.js 学习体验之旅】(1)ko初体验

    前言 什么,你现在还在看knockout.js?这货都已经落后主流一千年了!赶紧去学Angular.React啊,再不赶紧的话,他们也要变out了哦.身旁的90后小伙伴,嘴里还塞着山东的狗不理大蒜包, ...

  7. 在同一个硬盘上安装多个 Linux 发行版及 Fedora 21 、Fedora 22 初体验

    在同一个硬盘上安装多个 Linux 发行版 以前对多个 Linux 发行版的折腾主要是在虚拟机上完成.我的桌面电脑性能比较强大,玩玩虚拟机没啥问题,但是笔记本电脑就不行了.要在我的笔记本电脑上折腾多个 ...

  8. 百度EChart3初体验

    由于项目需要在首页搞一个订单数量的走势图,经过多方查找,体验,感觉ECharts不错,封装的很细,我们只需要看自己需要那种类型的图表,搞定好自己的json数据就OK.至于说如何体现出来,官网的教程很详 ...

  9. Python导出Excel为Lua/Json/Xml实例教程(二):xlrd初体验

    Python导出Excel为Lua/Json/Xml实例教程(二):xlrd初体验 相关链接: Python导出Excel为Lua/Json/Xml实例教程(一):初识Python Python导出E ...

随机推荐

  1. sql server中的分页数据查询

    1.引言 今天在工作中遇到一个需要进行sql server分页数据查询的问题,但是分页数据查询的sql却忘记了,最终通过查询资料解决了该问题.现在把解决方法记下,以备查阅. 在这里需要感谢博客园的Ql ...

  2. PyQt4 的部件 -- CheckBox 单选框

    单选框具有两种状态:被选中或未被选中. 当用户选择或者取消选择时,单选框就会发射一个stateChanged()信号 # QCheckBox 单选框 # 本例创建一个用来改变窗口标题的单选框 impo ...

  3. Python模块学习------ 多线程threading(2)

    一.避免使用thread模块,使用threading模块的原因: 1. 更高级别的threading模块更为先进,对线程的支持更加完善.而且使用thread模块的属性有可能会与threading 出现 ...

  4. 使用sysbench对mysql压力测试

    sysbench是一个模块化的.跨平台.多线程基准测试工具,主要用于评估测试各种不同系统参数下的数据库负载情况.关于这个项目的详细介绍请看:https://github.com/akopytov/sy ...

  5. H5数飞机

    当时进入民航大培训前做过一系列的测试,一共是8个小游戏,主要测试情景意识.反应能力.场面控制之类的,有几个还记忆犹新,这个数飞机只是其中之一,今天没事用JavaScript做了一遍. 原理 逻辑比较简 ...

  6. 谈谈关键字new

    1.在情人节那天,无意间看到空间有人说,没有对象就new一个,然后就可以........ 程序中我们常用到X a=new X(), new在这里是创建一个对象,也可以叫做创建一个实例,我们先谈谈后半部 ...

  7. 微信小程序--合法域名校验出错

    第一次做小demo的时候遇到一个问题,合法域名校验出错: 第一步:登陆微信公众号平台--个人中心--设置--开发设置--服务器域名(一个月只有5次修改机会一定要珍惜) 第二步 打开微信开发者工具,有个 ...

  8. 读书笔记《PHP与MySQL程序设计》一

    第1章 PHP概述 1.1  历史(PHP4.PHP5.PHP5.3.PHP6[未发布]) 1.2 一般语言特性(实用性.强大功能.可选择性.成本[开源]) 第2章 环境配置 2.1 安装的前提条件( ...

  9. 整理C++面试题for非CS程序猿——更新至【48】

    结合网上的C++面试题+自己的面经,进行整理记录,for我这种非CS的程序猿.(不定期更新,加入了自己的理解,如有不对,请指出) [1] new/delete和malloc/free的区别和联系? 1 ...

  10. Node+mongodb线上部署到阿里云

    Node+mongodb线上部署到阿里云 部署使用的主要工具是pm2+nginx,使用码云的私有仓库,自动部署到服务器,私有仓库和服务器要事先设置好免密码登录.使用DNSPOD进行域名解析.事先准备好 ...