楼主: pharos

[笔记] 测试驱动开发

[复制链接]
论坛徽章:
167
马上有对象
日期:2014-03-18 12:31:23ITPUB官方微博粉丝徽章
日期:2011-06-28 19:45:36现任管理团队成员
日期:2011-05-07 01:45:082011新春纪念徽章
日期:2011-02-18 11:43:342011新春纪念徽章
日期:2011-01-25 15:42:562011新春纪念徽章
日期:2011-01-25 15:42:332011新春纪念徽章
日期:2011-01-25 15:42:152011新春纪念徽章
日期:2011-01-25 15:41:502011新春纪念徽章
日期:2011-01-25 15:41:012011新春纪念徽章
日期:2011-01-04 10:36:18
11#
 楼主| 发表于 2006-5-23 13:08 | 只看该作者
  安装JUnit十分简单,只需在www.junit.org中下载最新的软件包(ZIP格式), 然后将其解压缩,并且将"JUnit安装目录\junit.jar" 以及"JUnit安装目录"都加到系统环境变量CLASSPATH中去即可。

  执行套件可以像上述程序一样在main方法中使用,也可以直接在命令行调用:java junit.textui.TestRunner 测试类名(文本格式)、java junit.awtui.TestRunner 测试类名(图形格式,AWT版)、java junit.swingui.TestRunner测试类名(图形版,Swing版)。
  编译执行(即在命令行执行javac testQueue.java和javatestQueue), 你会发现屏幕上出现提示:
  .E 一个小点说明执行了一个测试用例,E表示其失败
  Time: 0.11 说明执行测试共花费了0.11秒
  There was 1 error: 说明存在一个错误
  1) testEmpty(testQueue)java.lang.NoClassDefFoundError: Queue
    at testQueue.setUp(testQueue.java:13)
    at testQueue.main(testQueue.java:9)
  FAILURES!!!
  Tests run: 1, Failures: 0, Errors: 1
  测试没有通过是肯定的,因为Queue类都还没有写呢?怎么可能通过测试,因此,我们就编写以下代码,以使测试通过:
public class Queue extends java.util.Vector
{
public Queue()
{
super();
}
public boolean empty()
{
return super.isEmpty();
}
}
  将这个类编译后,再次执行测试程序,这时将出以下提示:
  . 一个小点说明执行了一个测试用例,没有E表示其成功
  Time: 0.11
  OK (1 test)
  你还可以使用前面我们说到的另两个命令,使测试反馈以图形化的形式体现出来,例如,执行java junit.awtui.TestRunner testQueue, 将出现:

图1

使用道具 举报

回复
论坛徽章:
167
马上有对象
日期:2014-03-18 12:31:23ITPUB官方微博粉丝徽章
日期:2011-06-28 19:45:36现任管理团队成员
日期:2011-05-07 01:45:082011新春纪念徽章
日期:2011-02-18 11:43:342011新春纪念徽章
日期:2011-01-25 15:42:562011新春纪念徽章
日期:2011-01-25 15:42:332011新春纪念徽章
日期:2011-01-25 15:42:152011新春纪念徽章
日期:2011-01-25 15:41:502011新春纪念徽章
日期:2011-01-25 15:41:012011新春纪念徽章
日期:2011-01-04 10:36:18
12#
 楼主| 发表于 2006-5-23 13:08 | 只看该作者
  第二次迭代
  接下来,我们修改测试程序,加入测试案例TC04、TC05的考虑。
import junit.framework.*;
public class testQueue extends TestCase
{
protected Queue q1,q2;
public static void main (String[] args)
{
junit.textui.TestRunner.run (suite());
}
protected void setUp() {
q1= new Queue();
q2= new Queue();
q2.inqueue("first"; /对队列q2执行插入队列操作
q2.inqueue("second";
}
public static Test suite()
{
return new TestSuite(testQueue.class);
}
public void testEmpty()
{
assertTrue(q1.empty());
//当队列新建时,应为空-TC01
}
public void testInqueue()
{
assertTrue(!(q2.empty()));
//执行了插入队列操作,队列就应不为空-TC05
assertEquals(1,q2.search("second");
//search方法用于确定元素在队列中的位置
//后插入的数据元素,应在未尾-TC04
//插入两个,第一个在位置0, 第二在位置1
}
}
  根据这个测试代码,我们需要在Queue类中添加上inqueue() 和search() 两个方法,如下所示:
public class Queue extends java.util.Vector
{
public Queue()
{
super();
}
public boolean empty()
{
return super.isEmpty();
}
public synchronized void inqueue (Object x)
{
super.addElement(x);
}
public int search(Object x)
{
return super.indexOf(x);
}
}

使用道具 举报

回复
论坛徽章:
167
马上有对象
日期:2014-03-18 12:31:23ITPUB官方微博粉丝徽章
日期:2011-06-28 19:45:36现任管理团队成员
日期:2011-05-07 01:45:082011新春纪念徽章
日期:2011-02-18 11:43:342011新春纪念徽章
日期:2011-01-25 15:42:562011新春纪念徽章
日期:2011-01-25 15:42:332011新春纪念徽章
日期:2011-01-25 15:42:152011新春纪念徽章
日期:2011-01-25 15:41:502011新春纪念徽章
日期:2011-01-25 15:41:012011新春纪念徽章
日期:2011-01-04 10:36:18
13#
 楼主| 发表于 2006-5-23 13:09 | 只看该作者
  编译之后,再次执行java junit.awtui.TestRunnertestQueue, 你将再次看到成功的绿色。


图2

  我们仔细看一下这一界面。
  1) 最上面列出了测试代码的类名,右边有一个"Run" 按钮,当你需要再次运行这一测试代码时,只需单击这个按钮。另外,将"Reload classesevery run" 选项打上勾很有用,当你测试未通过(出现红色时), 你可以转身去修改代码,修改完后,只需再按"Run" 按钮就可以再次运行。
  2) 中间区域是一个状态汇报区,红色表示未通过,统计了共运行了多少个测试(也就是在TestCase类中方法的数量)。
  3) 如果测试时出现错误,例如,我们不小心将"assertTrue(!(q2.empty()));" 误写成为"assertTrue(q2.empty());" 就将造成测试失败:
  注:由于第一个测试还是通过的,因此你会看到绿色条一闪。这时,你将会发现JUnit会将错误列出来,并且对应的"Run"按钮也由灰变成了亮,这表示你可以转身修改,完成后单击这个"Run按钮"可以只做刚才失效的这个测试,这将节省大量的时间。
  同时,在最下面的窗体里,列出了失效的详细原因。

使用道具 举报

回复
论坛徽章:
167
马上有对象
日期:2014-03-18 12:31:23ITPUB官方微博粉丝徽章
日期:2011-06-28 19:45:36现任管理团队成员
日期:2011-05-07 01:45:082011新春纪念徽章
日期:2011-02-18 11:43:342011新春纪念徽章
日期:2011-01-25 15:42:562011新春纪念徽章
日期:2011-01-25 15:42:332011新春纪念徽章
日期:2011-01-25 15:42:152011新春纪念徽章
日期:2011-01-25 15:41:502011新春纪念徽章
日期:2011-01-25 15:41:012011新春纪念徽章
日期:2011-01-04 10:36:18
14#
 楼主| 发表于 2006-5-23 13:09 | 只看该作者
  后面的迭代
到这里,开发还没有完成,但这种思想却已经通过这样两个短小的实践传递出去了,后面的活大家可以动手试一下。
  另外值得一提的是,这里虽然洋洋洒洒一大篇,实际两次迭代花费了我不到15分钟就完成了。而且,当看到绿条时,心里十分舒畅。
  一些遗憾
  文章到此就告一段落,但却有些许遗憾。
  遗憾之一:这只是一篇文章,没有办法把所有方面都讲得面面俱到,以致于大家可能无法马上上手。
   正是由于这样的原因,本文取名为"感悟", 与大家交流一下体会,希望能够帮助大家更好地接受"测试驱动开发"的理念,并开始着手实践。
  遗憾之二:笔者水平有限,无法解决大家的各种问题。
  让笔者感到欣慰的是,记载着这些答案的《测试驱动开发》、《敏捷软件开发》、《拥抱变化: 解析极限编程》等大作都已悉数摆上了中国的书店。路虽难走,但明师已有。
  实践永远是学习的最好方法,看到笔者的感悟,就开始极限之旅吧,因为那里风光无限,乐趣无限。当你掌握了测试驱动开发的精髓,那你就能够对你自己编写的所有代码充满信心,不再担心它们什么时候在你的后面放一冷箭,从此告别这给你带来无限压力的苦恼

使用道具 举报

回复
论坛徽章:
167
马上有对象
日期:2014-03-18 12:31:23ITPUB官方微博粉丝徽章
日期:2011-06-28 19:45:36现任管理团队成员
日期:2011-05-07 01:45:082011新春纪念徽章
日期:2011-02-18 11:43:342011新春纪念徽章
日期:2011-01-25 15:42:562011新春纪念徽章
日期:2011-01-25 15:42:332011新春纪念徽章
日期:2011-01-25 15:42:152011新春纪念徽章
日期:2011-01-25 15:41:502011新春纪念徽章
日期:2011-01-25 15:41:012011新春纪念徽章
日期:2011-01-04 10:36:18
15#
 楼主| 发表于 2006-5-23 13:09 | 只看该作者
用NUnit2.1简单实现.net的测试驱动开发(TDD)
下面的例子很简单,就是实现两个整数的四则运算,TDD提倡测试优先,即先写测试用例,再写运行代码,刚下了个NUnit2.1,迫不及待的试了试……
1最初的测试用例
using System;
using NUnit.Framework;
namespace netshop
{
     /// <summary>
     /// 四则运算TestCls测试用例
     /// Edit by spgoal
     /// </summary>
     [TestFixture]
     public class TestCase
     {
         public TestCase()
         {        
         }
         private TestCls tc;
         [SetUp]
         public void setup()
         {
              tc=new TestCls();
         }
         [Test]
         public void testAdd()
         {
              
              Assert.AreEqual(10,tc.Add(5,5));
              Assert.AreEqual(7,tc.Add(3,4));
         }
         [Test]
         public void testSub()
         {
              Assert.AreEqual(1,tc.Sub(5,4));
         }
         [Test]
         public void testMul()
         {
              Assert.AreEqual(10,tc.Mul(2,5));
         }
         [Test]
         public void testDiv()
         {
              Assert.AreEqual(2,tc.Div(10,5));
         }
     }
}

使用道具 举报

回复
论坛徽章:
167
马上有对象
日期:2014-03-18 12:31:23ITPUB官方微博粉丝徽章
日期:2011-06-28 19:45:36现任管理团队成员
日期:2011-05-07 01:45:082011新春纪念徽章
日期:2011-02-18 11:43:342011新春纪念徽章
日期:2011-01-25 15:42:562011新春纪念徽章
日期:2011-01-25 15:42:332011新春纪念徽章
日期:2011-01-25 15:42:152011新春纪念徽章
日期:2011-01-25 15:41:502011新春纪念徽章
日期:2011-01-25 15:41:012011新春纪念徽章
日期:2011-01-04 10:36:18
16#
 楼主| 发表于 2006-5-23 13:09 | 只看该作者
2 编译这个测试用例,理所当然的是通不过的,因为TestCls类未建立,于是建立该类,不必多说,看代码:
using System;
namespace netshop
{
     /// <summary>
     /// 四则运算的简单例子
     /// </summary>
     public class TestCls
     {
         public TestCls()
         {
         }
         //加法
         public int Add(int a,int b)
         {
              return 0;
         }
         //减法
         public int Sub(int a,int b)
         {
              return 0;
         }
         //乘法
         public int Mul(int a,int b)
         {
              return 0;
         }
         //除法
         public double Div(int a,int b)
         {
              return 0;
         }
     }
}
这时编译通过,但由于里面的方法没实现,所以所有测试用例都失败。
(加载测试用例的方法是:先运行Nunit-Gui V2.1程序,然后在菜单file—open—选择测试用例所在工程目录的bin目录下的dll文件。)

使用道具 举报

回复
论坛徽章:
167
马上有对象
日期:2014-03-18 12:31:23ITPUB官方微博粉丝徽章
日期:2011-06-28 19:45:36现任管理团队成员
日期:2011-05-07 01:45:082011新春纪念徽章
日期:2011-02-18 11:43:342011新春纪念徽章
日期:2011-01-25 15:42:562011新春纪念徽章
日期:2011-01-25 15:42:332011新春纪念徽章
日期:2011-01-25 15:42:152011新春纪念徽章
日期:2011-01-25 15:41:502011新春纪念徽章
日期:2011-01-25 15:41:012011新春纪念徽章
日期:2011-01-04 10:36:18
17#
 楼主| 发表于 2006-5-23 13:10 | 只看该作者
3 于是编写加减乘除四个函数的实现:
using System;
namespace netshop
{
     /// <summary>
     /// 四则运算的简单例子
     /// </summary>
     public class TestCls
     {
         public TestCls()
         {
         }
         //加法
         public int Add(int a,int b)
         {
              return a+b;
         }
         //减法
         public int Sub(int a,int b)
         {
              return a-b;
         }
         //乘法
         public int Mul(int a,int b)
         {
              return a*b;
         }
         //除法
         public double Div(int a,int b)
         {
              return a/b;
         }
     }
}

这时测试通过了!

使用道具 举报

回复
论坛徽章:
167
马上有对象
日期:2014-03-18 12:31:23ITPUB官方微博粉丝徽章
日期:2011-06-28 19:45:36现任管理团队成员
日期:2011-05-07 01:45:082011新春纪念徽章
日期:2011-02-18 11:43:342011新春纪念徽章
日期:2011-01-25 15:42:562011新春纪念徽章
日期:2011-01-25 15:42:332011新春纪念徽章
日期:2011-01-25 15:42:152011新春纪念徽章
日期:2011-01-25 15:41:502011新春纪念徽章
日期:2011-01-25 15:41:012011新春纪念徽章
日期:2011-01-04 10:36:18
18#
 楼主| 发表于 2006-5-23 13:10 | 只看该作者
4 寻找令测试失败的测试用例
想想似乎漏了一些可以使程序出错的测试用例,想到了吧?就是除数为零的情况,于是修改testDiv测试用例
         [Test]
         public void testDiv()
         {
              Assert.AreEqual(2,tc.Div(10,5));
              Assert.AreEqual(0,tc.Div(10,0));//除于0的情况
         }
果然,运行Nunit,出错了^_^  (这人有问题,出错了还笑-_-b)

使用道具 举报

回复
论坛徽章:
167
马上有对象
日期:2014-03-18 12:31:23ITPUB官方微博粉丝徽章
日期:2011-06-28 19:45:36现任管理团队成员
日期:2011-05-07 01:45:082011新春纪念徽章
日期:2011-02-18 11:43:342011新春纪念徽章
日期:2011-01-25 15:42:562011新春纪念徽章
日期:2011-01-25 15:42:332011新春纪念徽章
日期:2011-01-25 15:42:152011新春纪念徽章
日期:2011-01-25 15:41:502011新春纪念徽章
日期:2011-01-25 15:41:012011新春纪念徽章
日期:2011-01-04 10:36:18
19#
 楼主| 发表于 2006-5-23 13:10 | 只看该作者
于是修改TestCls类代码
         //除法
         public double Div(int a,int b)
         {
            if(b!=0)
            {
                return a/b;
            }
            else
            {
                return 0;
            }
         }
编译后,再运行Nunit,全部通过!

使用道具 举报

回复
论坛徽章:
167
马上有对象
日期:2014-03-18 12:31:23ITPUB官方微博粉丝徽章
日期:2011-06-28 19:45:36现任管理团队成员
日期:2011-05-07 01:45:082011新春纪念徽章
日期:2011-02-18 11:43:342011新春纪念徽章
日期:2011-01-25 15:42:562011新春纪念徽章
日期:2011-01-25 15:42:332011新春纪念徽章
日期:2011-01-25 15:42:152011新春纪念徽章
日期:2011-01-25 15:41:502011新春纪念徽章
日期:2011-01-25 15:41:012011新春纪念徽章
日期:2011-01-04 10:36:18
20#
 楼主| 发表于 2006-5-23 13:11 | 只看该作者
5 总结
这只是一个简单例子,因为以前用JUnit觉得还挺好用,于是想试试.net的Nunit是否好用,果然也不差:)测试优先只是测试驱动开发的一部分内容,还有重构等步骤,所以本文的题目有些名不副实,请大家多多包涵。

测试驱动的开发,让你消除代码中的bug
项目后期检讨主要集中于发现了多少个bug以及如何处理它们。在大多数情况下,你会发现CMM(能力成熟度模型)、六西格玛(six sigma)等软件质量控制方法下过程评价基本上都是围绕着如何减少缺陷以及管理缺陷的。


然而,尽管编写没有bug的软件是如此的重要,许多时间还是花费在消除bug而不是花在如何防止它们的出现这一更重要的步骤上。在单元测试(Unit Test)中,绝大多数开发者在完成单元之后才开始进行测试,而不是开发代码的同时进行测试。没有人可以责怪程序员,因为项目计划常常给代码编写安排了最少的时间。之所以这样,是由于人们常常相信他们的计划非常完善,因此编写代码也就很简单。不幸的是,实际情况往往并不是这样的。

使用道具 举报

回复

您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

TOP技术积分榜 社区积分榜 徽章 团队 统计 知识索引树 积分竞拍 文本模式 帮助
  ITPUB首页 | ITPUB论坛 | 数据库技术 | 企业信息化 | 开发技术 | 微软技术 | 软件工程与项目管理 | IBM技术园地 | 行业纵向讨论 | IT招聘 | IT文档
  ChinaUnix | ChinaUnix博客 | ChinaUnix论坛
CopyRight 1999-2011 itpub.net All Right Reserved. 北京盛拓优讯信息技术有限公司版权所有 联系我们 未成年人举报专区 
京ICP备16024965号-8  北京市公安局海淀分局网监中心备案编号:11010802021510 广播电视节目制作经营许可证:编号(京)字第1149号
  
快速回复 返回顶部 返回列表