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. COM学习(一)——COM基础思想

    概述 学习微软技术COM是绕不开的一道坎,最近做项目的时候发现有许多功能需要用到COM中的内容,虽然只是简单的使用COM中封装好的内容,但是许多代码仍然只知其然,不知其所以然,所以我决定从头开始好好学 ...

  2. 快速开发基于 HTML5 网络拓扑图应用--入门篇(二)

    上一篇我们绘制了一个 graphView 场景,在场景之上通过 graphView.dm() 获取数据容器,并通过 graphView.dm().add() 函数添加了两个 Node 节点,并通过 s ...

  3. Java学习笔记21---内部类之对成员内部类的补充说明(二)

    上篇文章--笔记20补充说明了前四点,这里接着来说剩下的两点. 要点如下: 5.访问权限修饰符可以修饰成员内部类 1).访问权限修饰符对内部类的访问限制与外部类的一般成员遵循一样的规则,具体请参考笔记 ...

  4. 安装cocoapods遇到的问题

    1.终端报下面的错误 ERROR:  While executing gem ... (Errno::EPERM) Operation not permitted - /usr/bin/pod 解决方 ...

  5. css的学习笔记

    CSS3有哪些新特性? 1. CSS3实现圆角(border-radius),阴影(box-shadow), 2. 对文字加特效(text-shadow.),线性渐变(gradient),旋转(tra ...

  6. [整理]k-vim-for-server通过vimrc修改vim格式

    1.备份原来的vim设置: cp ~/.vimrc ~/.vimrc_bak 2. 下载配置到指定目录 法一: curl https://raw.githubusercontent.com/wklke ...

  7. python中的与 和 或

    上周五写程序碰到需要处理多重判断的一个逻辑,一般正确的写法是: if a or b or (c and d) or e: pass 因为变量很长,看上去比较杂乱,自己灵机一动写成了如下的样子: if ...

  8. vb代码之-------当窗体BorderStyle属性为0时,添加窗口预览到任务栏

    入吾QQ群183435019 (学习 交流+唠嗑) 有很多时候,我们为了美观,将会自己画一个标题栏,这时候我们会把原来的标题栏取消掉,最简单的方法是吧窗体的BorderStyle设置成为0, 然后自己 ...

  9. MVVMLight 1:MVVMLight介绍以及在项目中的使用

    一.MVVM 和 MVVMLight介绍 MVVM是Model-View-ViewModel的简写.类似于目前比较流行的MVC.MVP设计模式,主要目的是为了分离视图(View)和模型(Model)的 ...

  10. 【批处理学习笔记】第十二课:常用DOS命令(2)

    文件管理type 显示文本文件的内容.copy 将一份或多份文件复制到另一个位置.del 删除一个或数个文件.move 移动文件并重命名文件和目录.(Windows XP Home Edition中没 ...