测试驱动开发(TDD)是极限编程(XP)的重要特点,它是以持续性的测试来推动代码的开发,即可以简化代码,又可以保证质量。它改变了先编写代码,后编写测试,而是先编写测试,然后在编写代码来满足测试的方法。这样使得测试工作不仅仅是单纯的测试,而成为了设计的一部分。对于刚入门的编程者来说,也许觉得非常地别扭,但是当你习惯了这种编程方式之后,你会发现,TDD会成为你的得力助手。
下面的内容就以学习JUnit这个测试工具来简单的介绍TDD。(注:本文主要内容是介绍JUnit的使用,顺便抛砖引玉介绍TDD的开发过程。想了解更多关于TDD,可以参考其他的一些专业书籍)。
开发环境是:Eclipse3.2,已经集成了JUnit,所以就对Junit的配置不做介绍(网上这种文章太多了)。
第一章:JUnit快速入门:
需求:需要一个工具类,可以实现2个数的加、减、乘、除四个功能。我们给这个类起名叫CalculateUtil。
先编写测试代码:
- import junit.framework.TestCase;
- public class CalculateUtilTest extends TestCase
- {
- public void testCreate()
- {
- new CalculateUtil();
- }
- }
代码解释:
1行:导入JUnit必须的类
2行:任何一个测试类必须集成TestCase类。
测试类的类名命名 方式:被测试类类名+Test。这是一种比较好的习惯,
比如从CalculateUtilTest这个名称就知道被测试类是CalculateUtil
3行:测试类的测试方法。所有的测试方法都必须以test单词开头,并且方法的返
回类型为void。
编写完测试代码之后在Eclipse中运行该测试类,发现Junit运行出错(显示了一条红色杠)
这是在预料之中,因为我们还没有编写CalculateUtil类。为了使测试通过,那么下面开始编写CalculateUtil类。CalculateUtil类代码如下:
- public class CalculateUtil
- {
- }
然后再次运行测试类。这时会发现测试成功。
- import junit.framework.TestCase;
- public class CalculateUtilTest extends TestCase
- {
- public void testCreate()
- {
- CalculateUtil ca=new CalculateUtil();
- assertEquals(5, ca.add(3,2));
- }
- }
在这里代码稍微改变了一下,使用ca引用来指向生成的CalculateUtil对象。
代码解释:
1行:测试类的方法必须以单词test开头
2行:assertEquals()方法。以assert单词开头的方法就是JUnit测试框架中的断
言方法。比如assertEquals(5, ca.add(3,2)); 方法就是断言ca的add(3,2)方
法返回的结果等于5。如果add(3,2)返回5那么测试成功,否则测试失败。
运行测试类,这时测试失败。那么向CalculateUtil中添加代码来保证测试成功:
- public class CalculateUtil
- {
- public int add(int numOne,int numTwo)
- {
- return numOne+numTwo;
- }
- }
为了验证add方法是否是真的返回两个数的相加的结果,我们继续在添加一行测试代码:
- assertEquals(7, ca.add(4,2));
再运行会发现测试出错
故障跟踪中错误描述为:
junit.framework.AssertionFailedError:expected:<7> but was <6>
(如果你英语不是很差的话,相信这句话不用我解释也明白了)。在测试的时候,要选用一些容易出错的边界值进行测试,有正确的测试用例也要有错误的测试用例。
在完成add方法之后,下面开始进行除法的编写。首先编写测试代码:
- import junit.framework.TestCase;
- public class CalculateUtilTest extends TestCase
- {
- public void testCreate()
- {
- CalculateUtil ca=new CalculateUtil();
- assertEquals(5, ca.add(3,2));
- }
- public void testDivision()
- {
- CalculateUtil ca=new CalculateUtil();
- assertEquals("两个数相除", 2,ca.division(4, 2));
- }
- }
代码解释:
1行:assertEquals("两个数相除", 2,ca.division(4, 2));和前面assertEquals方法
不一样,该方法多了一个参数,这个参数就是对该测试的一个简单的描述。
如果测试失败,那么会有提示。
为了使测试通过,就要在CalculateUtil类中添加一个division方法。代码如下:
- public class CalculateUtil
- {
- public int add(int numOne,int numTwo)
- {
- return numOne+numTwo;
- }
-
- public int division(int numOne,int numTwo)
- {
- return numOne/numTwo;
- }
- }
运行测试代码,测试通过。那么这样就可以了吗?由于除法非常特殊,如果除数为0那么会怎么样呢?我们继续在testDivision()中添加一行测试代码测试除数为0的情况:
- public void testDivision()
- {
- CalculateUtil ca=new CalculateUtil();
- assertEquals("两个数相除", 2,ca.division(4, 2));
- assertEquals("除数为0:", 2,ca.division(4,0));
- }
运行测试,会发现testDivision()方法抛出了异常。
测试表明:当除数为0的时,方法division()生成了一个异常。那么我们希望在测试用例中捕获该异常。更改后的testDivision()方法如下:
- public void testDivision()
- {
- CalculateUtil ca=new CalculateUtil();
- assertEquals("两个数相除:", 2,ca.division(4,2));
- try
- {
- assertEquals("除数为0:", 2,ca.division(4,0));
- fail("除数不为0");
- }
- catch(ArithmeticException ex){}
- }
代码解释:fail()一旦被执行,会立即中止测试,java虚拟机不再执行任何别的代码,并且会抛出junit.framework.AssertionFailedError异常。结合上面的try-catch语句,如果产生异常,那么会忽略fail()方法,如果没有产生异常那么就会调用fail()方法使测试失败,用这种方式就可以测试是否有异常产生,如果抛出异常,那么测试通过,否则测试失败。再次运行测试用例,一条绿杠显示测试通过。
但是这样还是不妥,因为类CalculateUtil毕竟是不知道测试类的存在,虽然在测试类中用异常捕获,但是一旦脱离测试类,那么division()方法的健壮性还是受到质疑。所以从新修改division()方法
- public int division(int numOne,int numTwo)throws ArithmeticException
- {
- return numOne/numTwo;
- }
再重新运行测试用例,测试通过。
注:处理异常的方式很多,这里只是其中一种做法。也可以在division()方法中写一段业务逻辑,判断numTwo是否为0,如果为0则抛出异常等……,在这里不做深入讨论。
从刚才的几个例子中,可以大概的知道TDD的开发思路,也知道JUnit的基本用法。但当我们反观CalculateUtilTest 类中的测试方法可以发现:类中的两个测试方法都构造了CalculateUtil的对象ca,但是对于程序来说,我们只需要构造一个对象即可。我们可以对CalculateUtilTest类中的代码稍作修改。修改后代码如下:
- public class CalculateUtilTest extends TestCase
- {
- private CalculateUtil ca;
- protected void setUp() throws Exception
- {
- ca=new CalculateUtil();
- }
-
- public void testCreate()
- {
- assertEquals(5, ca.add(3,2));
- assertEquals(7, ca.add(4,2));
- }
-
- public void testDivision()
- {
- CalculateUtil ca=new CalculateUtil();
- assertEquals("两个数相除:", 2,ca.division(4,2));
- try
- {
- assertEquals("除数为0:", 2,ca.division(4,0));
- fail("除数不为0");
- }
- catch(ArithmeticException ex){}
- }
- }
代码解释:
1行:JUnit在执行每个测试之前都先执行setUp方法,可以将公共的测试初始化代码放在setUp方法中。与setUp功能方法相反的是protected void tearDown() throws Exception方法;可以将测试结束后要执行的收尾工作放入tearDown方法中,比如:关闭数据库连接,关闭流……
分享到:
相关推荐
在“测试驱动开发with Junit(三)”这一主题中,我们将会深入探讨如何利用Java中的JUnit框架进行TDD实践。 JUnit是Java编程语言中最常用的单元测试框架之一,它为开发者提供了方便快捷的方式来编写和运行可重复的...
总结,测试驱动开发With Junit涉及到的主要知识点包括: - TDD(测试驱动开发)的概念和流程 - JUnit作为Java的单元测试框架,如何创建测试类和测试方法 - 如何使用`assert`方法进行断言,确保代码行为正确 - 创建和...
本文将深入讲解JUnit 4的关键特性和如何进行测试驱动开发。 1. 预备知识 在开始使用JUnit 4进行测试之前,了解一些预备知识是必要的。例如,Java 5引入的可变长参数(Variable-Length Arguments)允许函数接收不定...
《Pragmatic Unit Testing in Java with JUnit》是一本专注于Java单元测试实践的书籍,其配套源代码提供了丰富的示例和实践案例,帮助读者深入理解如何有效地使用JUnit进行单元测试。JUnit是Java领域最广泛使用的...
2. `@RunWith(SpringRunner.class)`:这是一个JUnit runner,它使得Spring TestContext Framework可以驱动测试执行。 3. `@SpringBootTest`:这个注解用于启动一个Spring应用上下文,可以指定配置类、web环境等。 ...
这个"junit4测试源码"可能包含了JUnit4框架的源代码,使得用户能够深入理解其内部工作原理,便于自定义扩展或学习测试驱动开发(TDD)的最佳实践。 首先,JUnit4引入了注解(Annotation)的概念,使得测试类和测试...
10. **TDD(测试驱动开发)**:JUnit也支持采用TDD(Test-Driven Development)模式,即先写测试,再编写能通过测试的代码,这有助于提高代码质量和可维护性。 总之,JUnit作为Java的主流测试工具,其强大功能和...
在实际项目中,应当结合TDD(测试驱动开发)理念,先编写测试再实现功能,确保代码质量从一开始就得到保障。 总之,软件测试是保障软件质量的重要手段,而Junit作为Java的主流单元测试框架,为开发者提供了强大的...
【标题】"junit4 单元测试源码"涉及的是Java编程中单元测试的重要工具...通过分析和运行这些源码,学习者可以掌握单元测试的基本概念,了解如何编写有效的测试用例,以及如何利用Eclipse的集成环境进行测试驱动开发。
《Pragmatic Unit Testing in Java with JUnit》是一本专注于Java单元测试的指南,它深入讲解了如何有效地利用JUnit框架进行测试驱动开发(TDD)。JUnit是Java领域中最广泛使用的单元测试框架,它为开发者提供了编写...
Junit单元测试是Java开发中的一个关键组成部分,它允许开发者对代码进行小规模的验证,确保每个函数或方法按照预期工作。本指南将深入探讨Junit的使用,帮助你掌握如何编写、运行和理解单元测试。 一、Junit简介 ...
使用这个工具,开发者可以在Matlab中实现类似Java的测试驱动开发(TDD)或行为驱动开发(BDD)实践,从而提升代码质量和维护性。同时,通过JUnit兼容的XML输出,可以方便地将Matlab项目集成到更广泛的软件开发流程中。
- **Al Koscielny**(软件开发者):“如果在我开始进行测试驱动开发时就有这本书就好了。” - **Andrew Thompson**(顾问,Greenbrier & Russel):“虽然我对测试并不陌生,但我仍然在很多方面感到困惑。我认为这...
这对于测试驱动开发(TDD)非常有用,因为它允许我们专注于单个方法的逻辑,而不是依赖其他组件。 在Spring MVC框架中,JUnit同样扮演着关键角色。Spring MVC是Spring框架的一部分,专门用于构建Web应用程序。当...