文章目录
JUnit是一个开源的Java编程语言的单元测试框架,最初由 Erich Gamma 和 Kent Beck 编写。Junit测试是一种白盒测试工具。JUnit是一套框架,继承TestCase类,就可以用Junit进行自动测试了。具有JUnit经验对于应用“测试驱动开发(TDD)”的程序开发模型是非常重要的。
JUnit本质上是一套框架,即开发者制定了一套条条框框,遵循这此条条框框要求编写测试代码,如继承某个类,实现某个接口,就可以用JUnit进行自动测试了。
由于JUnit相对独立于所编写的代码,可以测试代码的编写可以先于实现代码的编写,XP 中推崇的 test first design的实现有了现成的手段:用JUnit写测试代码,写实现代码,运行测试,测试失败,修改实现代码,再运行测试,直到测试成功。以后对代码的修改和优化,运行测试成功,则修改成功。
Java 下的 team 开发,采用 cvs(版本控制) + ant(项目管理) + JUnit (集成测试) 的模式时,通过对ant的配置,可以很简单地实现测试自动化。
(1) 从http://www.junit.org或者此资源(提取码:1234)下载Junit。
(2) 解包Junit-4.X,得到如图的解包文件。

Junit文件说明:
junit.jar:JUnit框架结构、扩展和测试运行器的二进制发布
src.jar:JUnit的源代码,包括一个 Ant 的buildfile文件
junit:是个目录,内有JUnit自带的用JUnit编写的测试示例程序
javadoc:JUnit完整的API文档
doc:一些文档和文章,包括“Test Infected: Programmers Love Writing Tests”和其它一些资料,可以帮助我们入门。
(3) 配置。
步骤如下:
①右击“我的电脑”-“属性”-高级-环境变量;
②在系统变量中选择“CLASSPATH”,添加如下变量值:

③检验:打开cmd
输入命令:java org.junit.runner.JUnitCore org.junit.tests.AllTests
配置成功,如图下图所示。

使用JUnit 的最佳实践:
(1)新建一个名为test的source folder,用于存放测试类源代码;
(2)目标类与测试类应该位于同一个包下面,这样测试类中就不必导入源代码所在的包,因为他们位于同一个包下面;
(3)测试类的命名规则:假如目标类是Calculator,那么测试类应该命名为TestCalculator或者是CalculatorTest。
下面将以一个具体的实例进行说明。
(1) 新建一个 Java Project。命名为JunItTest,然后配置构建路径Add Library-JUnit 4。
在Java Build Path-Libraries上点击Add Library…选择JUnit导入

选择JUnit 4

(2) 建一个包com.test 并在此包下建一个除法类:Divide。

Divide类的程序源代码如下所示:
package com.test;
public class Divide {
private static int result;
public void divide(int num)
{
result/=num;
}
public int getResult()
{
return result;
}
public void setResult(int result)
{
Divide.result=result;
}
}
(3)右键Divide类,新建JUnit Test Case



Eclipse会自动为测试类取名:被测试类+Test,单击Next就可以了。选择需要进行测试的方法。
注意:测试类之所以使用“Test”开头或“Test”结尾,是为了更好的区分测试类与被测试类。

(4)创建测试用例。首先创建一个默认的测试用例。

执行测试用例。如图所示。
测试结果:红色,测试失败。

(5)修改测试用例:DivideTest.java。具体代码如下所示。
package com.test;
import static org.junit.Assert.*;
import org.junit.Before;
import org.junit.Test;
public class DivideTest {
private static Divide div=new Divide();
@Before
public void init()
{
div.setResult(10);
}
@Test
public void testDivide() {
div.divide(10);
assertEquals(1, div.getResult());
}
@Test(expected=Exception.class)
public final void dividezero()
{
div.divide(0);
}
}
注意:测试方法必须使用注解 org.junit.Test 修饰。 测试方法必须使用 public void 修饰,而且不能带有任何参数。测试方法在JUnit4.X中没有要求,但是为了使得命名意义,一般推荐采用“test”+“被测试方法”的命名规则。assertEquals 是由 JUnit 提供的一系列判断测试结果是否正确的静态断言方法(位于类 org.junit.Assert 中)之一,我们使用它将执行结果 result 和预期值“result”进行比较,来判断测试是否成功。
新测试用例运行后的测试结果如下图所示图所示。

绿色的进度条提示我们,测试运行通过了。但现在就宣布代码通过了单元测试还为时过早。记住:你的单元测试代码不是用来证明你是对的,而是为了证明你没有错。因此单元测试的范围要全面,比如对边界值、正常值、错误值得测试;对代码可能出现的问题要全面预测,而这也正是需求分析、详细设计环节中要考虑的。
(1)应用JUnit对类WordDealUtil编写测试代码
被测试程序说明:对名称、地址等字符串格式的内容进行格式检查。将Java对象名称(每个单词的头字母大写)按照数据库命名的习惯进行格式化格式化后的数据为小写字母,并且使用下划线分割命名单词。
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* 对名称、地址等字符串格式的内容进行格式检查
* 或者格式化的工具类
*/
public class WordDealUtil {
/**
* 将Java对象名称(每个单词的头字母大写)按照
* 数据库命名的习惯进行格式化
* 格式化后的数据为小写字母,并且使用下划线分割命名单词
* 例如:employeeInfo 经过格式化之后变为 employee_info
* @param name Java对象名称
*/
public static String wordFormat4DB(String name){
Pattern p = Pattern.compile("[A-Z]");
Matcher m = p.matcher(name);
StringBuffer sb = new StringBuffer();
while(m.find()){
m.appendReplacement(sb, "_"+m.group());
}
return m.appendTail(sb).toString().toLowerCase();
}
}
(2)添加测试代码。
import static org.junit.Assert.assertEquals;
import org.junit.Test;
public class TestWordDealUtil {
//测试wordFormat4DB正常运行的情况
@Test public void wordFormat4DBNormal(){
String target = "employeeInfo";
String result = WordDealUtil.wordFormat4DB(target);
assertEquals("employee_info", result);
}
}
推荐每编写完一个测试方法,则执行”run”
看测试结果,测试结果通过:

(3)继续添加测试代码,并运行看测试结果。
public class TestWordDealUtil {
//测试 null 时的处理情况
@Test public void wordFormat4DBNull(){
String target = null;
String result = WordDealUtil.wordFormat4DB(target);
assertNull(result);
}
//测试空字符串的处理情况
@Test public void wordFormat4DBEmpty(){
String target = "";
String result = WordDealUtil.wordFormat4DB(target);
assertEquals("", result);
}
//测试当首字母大写时的情况
@Test public void wordFormat4DBegin(){
String target = "EmployeeInfo";
String result = WordDealUtil.wordFormat4DB(target);
assertEquals("employee_info", result);
}
//测试当尾字母为大写时的情况
@Test public void wordFormat4DBEnd(){
String target = "employeeInfoA";
String result = WordDealUtil.wordFormat4DB(target);
assertEquals("employee_info_a", result);
}
//测试多个相连字母大写时的情况
@Test public void wordFormat4DBTogether(){
String target = "employeeAInfo";
String result = WordDealUtil.wordFormat4DB(target);
assertEquals("employee_a_info", result);
}
}
(4)分析测试结果

测试 null 时的处理情况与测试当首字母大写时的情况出现问题,需要修改源代码
(6)修改代码为:
public class WordDealUtil {
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());
}
return m.appendTail(sb).toString().toLowerCase();
}
}
测试结果:

至此,现在的代码已经比较稳定。
很好奇,就使用rubyonrails自动化单元测试而言,你们正在做什么?您是否创建了一个脚本来在cron中运行rake作业并将结果邮寄给您?git中的预提交Hook?只是手动调用?我完全理解测试,但想知道在错误发生之前捕获错误的最佳实践是什么。让我们理所当然地认为测试本身是完美无缺的,并且可以正常工作。下一步是什么以确保他们在正确的时间将可能有害的结果传达给您? 最佳答案 不确定您到底想听什么,但是有几个级别的自动代码库控制:在处理某项功能时,您可以使用类似autotest的内容获得关于哪些有效,哪些无效的即时反馈。要确保您的提
在控制台中反复尝试之后,我想到了这种方法,可以按发生日期对类似activerecord的(Mongoid)对象进行分组。我不确定这是完成此任务的最佳方法,但它确实有效。有没有人有更好的建议,或者这是一个很好的方法?#eventsisanarrayofactiverecord-likeobjectsthatincludeatimeattributeevents.map{|event|#converteventsarrayintoanarrayofhasheswiththedayofthemonthandtheevent{:number=>event.time.day,:event=>ev
对于具有离线功能的智能手机应用程序,我正在为Xml文件创建单向文本同步。我希望我的服务器将增量/差异(例如GNU差异补丁)发送到目标设备。这是计划:Time=0Server:hasversion_1ofXmlfile(~800kiB)Client:hasversion_1ofXmlfile(~800kiB)Time=1Server:hasversion_1andversion_2ofXmlfile(each~800kiB)computesdeltaoftheseversions(=patch)(~10kiB)sendspatchtoClient(~10kiBtransferred)Cl
我正在编写一个包含C扩展的gem。通常当我写一个gem时,我会遵循TDD的过程,我会写一个失败的规范,然后处理代码直到它通过,等等......在“ext/mygem/mygem.c”中我的C扩展和在gemspec的“扩展”中配置的有效extconf.rb,如何运行我的规范并仍然加载我的C扩展?当我更改C代码时,我需要采取哪些步骤来重新编译代码?这可能是个愚蠢的问题,但是从我的gem的开发源代码树中输入“bundleinstall”不会构建任何native扩展。当我手动运行rubyext/mygem/extconf.rb时,我确实得到了一个Makefile(在整个项目的根目录中),然后当
我构建了两个需要相互通信和发送文件的Rails应用程序。例如,一个Rails应用程序会发送请求以查看其他应用程序数据库中的表。然后另一个应用程序将呈现该表的json并将其发回。我还希望一个应用程序将存储在其公共(public)目录中的文本文件发送到另一个应用程序的公共(public)目录。我从来没有做过这样的事情,所以我什至不知道从哪里开始。任何帮助,将不胜感激。谢谢! 最佳答案 无论Rails是什么,几乎所有Web应用程序都有您的要求,大多数现代Web应用程序都需要相互通信。但是有一个小小的理解需要你坚持下去,网站不应直接访问彼此
我尝试运行2.x应用程序。我使用rvm并为此应用程序设置其他版本的ruby:$rvmuseree-1.8.7-head我尝试运行服务器,然后出现很多错误:$script/serverNOTE:Gem.source_indexisdeprecated,useSpecification.Itwillberemovedonorafter2011-11-01.Gem.source_indexcalledfrom/Users/serg/rails_projects_terminal/work_proj/spohelp/config/../vendor/rails/railties/lib/r
我有一个围绕一些对象的包装类,我想将这些对象用作散列中的键。包装对象和解包装对象应映射到相同的键。一个简单的例子是这样的:classAattr_reader:xdefinitialize(inner)@inner=innerenddefx;@inner.x;enddef==(other)@inner.x==other.xendenda=A.new(o)#oisjustanyobjectthatallowso.xb=A.new(o)h={a=>5}ph[a]#5ph[b]#nil,shouldbe5ph[o]#nil,shouldbe5我试过==、===、eq?并散列所有无济于事。
我有一些Ruby代码,如下所示:Something.createdo|x|x.foo=barend我想编写一个测试,它使用double代替block参数x,这样我就可以调用:x_double.should_receive(:foo).with("whatever").这可能吗? 最佳答案 specify'something'dox=doublex.should_receive(:foo=).with("whatever")Something.should_receive(:create).and_yield(x)#callthere
刚入门rails,开始慢慢理解。有人可以解释或给我一些关于在application_controller中编码的好处或时间和原因的想法吗?有哪些用例。您如何为Rails应用程序使用应用程序Controller?我不想在那里放太多代码,因为据我了解,每个请求都会调用此Controller。这是真的? 最佳答案 ApplicationController实际上是您应用程序中的每个其他Controller都将从中继承的类(尽管这不是强制性的)。我同意不要用太多代码弄乱它并保持干净整洁的态度,尽管在某些情况下ApplicationContr
Sinatra新手;我正在运行一些rspec测试,但在日志中收到了一堆不需要的噪音。如何消除日志中过多的噪音?我仔细检查了环境是否设置为:test,这意味着记录器级别应设置为WARN而不是DEBUG。spec_helper:require"./app"require"sinatra"require"rspec"require"rack/test"require"database_cleaner"require"factory_girl"set:environment,:testFactoryGirl.definition_file_paths=%w{./factories./test/