CSDN博客

img xv987654321xv

JUnit综述

发表于2004/10/19 11:16:00  2451人阅读

第1章.     软件测试

JUnit is an open source Java testing framework used to write and run repeatable tests

1.1.  测试分类

²       白盒测试——把测试对象看作一个打开的盒子,程序内部的逻辑结构和其他信息对测试人员是公开的。

²       回归测试——软件或环境的修复或更正后的“再测试”,自动测试工具对这类测试尤其有用。

²       单元测试——是最小粒度的测试,以测试某个功能或代码块。一般由程序员来做,因为它需要知道内部程序设计和编码的细节。

   

JUnit ——是一个开发源代码的Java测试框架,用于编写和运行可重复的测试。他是用于单元测试框架体系xUnit的一个实例(用于java语言)。主要用于白盒测试,回归测试。

 

1.2.  单元测试概述

1.2.1.  单元测试的好处

1)        提高开发速度——测试是以自动化方式执行的,提升了测试代码的执行效率。

2)        提高软件代码质量——它使用小版本发布至集成,便于实现人员除错。同时引入重构概念,让代码更干净和富有弹性。

3)        提升系统的可信赖度——它是回归测试的一种。支持修复或更正后的“再测试”,可确保代码的正确性。

1.2.2.  单元测试的针对对象

²       面向过程的软件开发针对过程。

²       面向对象的软件开发针对对象。

²       可以做类测试,功能测试,接口测试(最常用于测试类中的方法)。

1.2.3.  单元测试工具和框架

目前的最流行的单元测试工具是xUnit系列框架,常用的根据语言不同分为JUnitjava),CppUnitC++),DUnit Delphi ),NUnit.net),PhpUnitPhp )等等。该测试框架最早来自SmallTalk的SUnit,而最杰出的应用则是由Erich Gamma (《设计模式》的作者)和Kent BeckXPExtreme Programming)的创始人 )提供的开放源代码的JUnit

 

 

 

第2章.     Junit入门

2.1.  JUnit的优点

²       可以使测试代码与产品代码分开;

²       针对某一个类的测试代码通过较少的改动便可以应用于另一个类的测试;

²       易于集成到测试人员的构建过程中,JUnitAnt的结合可以实施增量开发;

²       JUnit是公开源代码的,可以进行二次开发;

²       可以方便地对JUnit进行扩展;

 

2.2.  JUnit单元测试编写原则

2.2.1.   “先写测试,再写代码”

²       从技术上强制你先考虑一个类的功能,也就是这个类提供给外部的接口,而不至于太早陷入它的细节。这是面向对象提倡的一种设计原则。

²       好的测试其实就是一个好的文档。这个类使用者往往可以通过查看这个类的测试代码了解它的功能。特别的,如果你拿到别人的一个程序,对他写测试是最好的了解这个程序的功能的方法。 xp的原则是make it simple,不是很推荐另外写文档,因为项目在开发过程中往往处于变动中,如果在早期写文档,以后代码变动后还得同步文档,多了一个工作,而且由于项目时间紧往往文档写的不全或与代码不一致,与其这样,不如不写。而如果在项目结束后再写文档,开发人员往往已经忘记当时写代码时的种种考虑,况且有下一个项目的压力,管理人员也不愿意再为旧的项目写文档。导致以后维护的问题。

²       没有人能保证需求不变动,以往项目往往对需求的变动大为头疼,害怕这个改动会带来其他地方的错误。为此,除了设计好的结构以分割项目外(松耦合),但如果有了测试,并已经建立了一个好的测试框架,对于需求的变动,修改完代码后,只要重新运行测试代码,如果测试通过,也就保证了修改的成功,如果测试中出现错误,也会马上发现错在哪里。修改相应的部分,再运行测试,直至测试完全通过。

2.2.2.  objective test + replicable test = simple test programme

objectivereplicableunit testing的最关心的两样东西。

objective意味着每个TestCase都应该是有目的的,并非人云亦云的“每个class都应该进行unit testing”;replicable则意味着TestCase应该是可重用的。Junit作为一个unit testingframework,十分好的尊重了这两条原则,很大程度上都由编写TestCase的人员来控制objective特性,而且replicable的方法和API也很大程度地提高了开发人员在编写TestCase上的效率。只要开发人员真正认识到了unit testing的必要性,他就一定会喜欢junit带来的好处,并非单纯的跟风的学习和使用。要知道Junit是能够真正提高开发效率和代码质量的。

 

2.2.3.  一般原则

²       是简化测试的编写,这种简化包括测试框架的学习和实际测试单元的编写。

²       是使测试单元保持持久性。

²       是可以利用既有的测试来编写相关的测试。

 

2.3.  JUnit的特征

²       使用断言方法判断期望值和实际值差异,返回Boolean值;

²       测试驱动设备使用共同的初始化变量或者实例;

²       测试包结构便于组织和集成运行;

²       支持图型交互模式和文本交互模式;

 

2.4.  JUnit框架组成

JUnit框架是一个典型的Composite模式。

TestSuite可以容纳任何派生自Test的对象;当调用TestSuite对象的run()方法是,会遍历自己容纳的对象,逐个调用它们的run()方法

1)        TestCase,对测试目标进行测试的方法与过程集合,可称为测试用例

2)        TestSuite测试用例的集合,可容纳多个测试用例(TestCase),将其称作测试包

3)        TestResult测试结果的描述与记录

4)        TestListener测试过程中的事件监听者

5)        TestFailure每一个测试方法所发生的与预期不一致状况的描述,称其测试失败元素

6)        AssertionFailedError JUnit Framework中的出错异常

 

2.5.  JUnit中常用的接口和类

2.5.1.  Test接口——运行测试和收集测试结果

Test接口使用了Composite设计模式,是单独测试用例 TestCase),聚合测试模式(TestSuite)及测试扩展(TestDecorator)的共同接口。

它的public int countTestCases()方法,它来统计这次测试有多少个TestCase,另外一个方法就是public void run TestResult ),TestResult是实例接受测试结果, run方法执行本次测试。

2.5.2.  TestCase抽象类——定义测试中固定方法

2.5.2.1.   定义

TestCaseTest接口的抽象实现,(不能被实例化,只能被继承)其构造函数TestCase(string name)根据输入的测试名称name创建一个测试实例。由于每一个TestCase在创建时都要有一个名称,若某测试失败了,便可识别出是哪个测试失败。

TestCase类中包含的setUp()tearDown()方法。setUp()方法集中初始化测试所需的所有变量和实例,并且在依次调用测试类中的每个测试方法之前再次执行setUp()方法。tearDown()方法则是在每个测试方法之后,释放测试程序方法中引用的变量和实例。

 开发人员编写测试用例时,只需继承TestCase,来完成run方法即可,然后JUnit获得测试用例,执行它的run方法,把测试结果记录在TestResult之中。

2.5.2.2.   注意事项

²       测试的独立性:一次只测试一个对象,方便定位出错的位置。这有2层意思:一个TestCase,只测试一个对象;一个TestMethod,只测试这个对象中的一个方法;

²       给测试方法一个合适的名字;

²       assert函数中给出失败的原因,如:assertTrue( “… should be true,  ……),方便查错。在这个例子中,如果无法通过assertTrue,那么给出的消息将被显示。在junit中每个assert函数都有第一个参数是出错时显示消息的函数原型;

²       测试所有可能引起失败的地方,如:一个类中频繁改动的函数。对于那些仅仅只含有getter/setter的类,如果是由IDE(如Eclipse)产生的,则可不测;如果是人工写,那么最好测试一下;

²       setUptearDown中的代码不应该是与测试方法相关的,而应该是全局相关的。如针对与测试方法AB,在setUptearDown中的代码应该是AB都需要的代码;

²       测试代码的组织:相同的包,不同的目录。这样,测试代码可以访问被测试类的protected变量/方法,方便测试代码的编写。放在不同的目录,则方便了测试代码的管理以及代码的打包和发布;

src   <=源代码根目录

 |---com

     |---mod1

         |---class1

junit   <=测试代码根目录

 |---com

     |---mod1

         |---class1

 

2.5.3.  Assert静态类——一系列断言方法的集合

Assert包含了一组静态的测试方法,用于期望值和实际值比对是否正确,即测试失败,Assert类就会抛出一个AssertionFailedError异常,JUnit测试框架将这种错误归入Failes并加以记录,同时标志为未通过测试。如果该类方法中指定一个String类型的传参则该参数将被做为AssertionFailedError异常的标识信息,告诉测试人员改异常的详细信息。

JUnit 提供了6大类31组断言方法,包括基础断言、数字断言、字符断言、布尔断言、对象断言。

其中assertEqualsObject expcted,Object actual)内部逻辑判断使用equals()方法,这表明断言两个实例的内部哈希值是否相等时,最好使用该方法对相应类实例的值进行比较。而assertSameObject expected,Object actual)内部逻辑判断使用了Java运算符“==”,这表明该断言判断两个实例是否来自于同一个引用(Reference),最好使用该方法对不同类的实例的值进行比对。asserEquals(String message,String expected,String actual)该方法对两个字符串进行逻辑比对,如果不匹配则显示着两个字符串有差异的地方。ComparisonFailure类提供两个字符串的比对,不匹配则给出详细的差异字符。

2.5.4.  TestSuite测试包类——多个测试的组合

2.5.4.1.   定义

    TestSuite类负责组装多个Test Cases。待测得类中可能包括了对被测类的多个测试,而TestSuit负责收集这些测试,使我们可以在一个测试中,完成全部的对被测类的多个测试,而不论测试是否在同一文件里。

TestSuite类实现了Test接口,且可以包含其它的TestSuites。它可以处理加入Test时的所有抛出的异常。

 

  清单A显示我们的测试包包含两个测试:

         Listing A: Test suite           

 

              public static Test suite() {

 

                TestSuite suite = new TestSuite();

 

                suite.addTest(new XMLTest("testPersonCount"));

 

                suite.addTest(new XMLTest("testContainsPerson"));

 

                return suite;

 

              }

 

2.5.4.2.   规约

TestSuite处理测试用例有6个规约(否则会被拒绝执行测试)

1)        测试用例必须是公有类(Public

2)        测试用例必须继承与TestCase 

3)        测试用例的测试方法必须是公有的( Public

4)        测试用例的测试方法必须被声明为Void

5)        测试用例中测试方法的前置名词必须是test

6)        测试用例中测试方法误任何传递参数

 

2.5.4.3.   如何利用测试包执行测试?

    执行测试需要创建可执行类来调用Junit测试运行器。运行器(runner)负责执行测试包(test suite),运行所有的测试并输出测试结果。

    清单B显示了如何把测试包集成到测试运行器中:

       Listing B: XMLTestRunner.java

       import junit.framework.Test;

       import junit.framework.TestSuite;

       import XMLTest;

 

       public class XMLTestRunner {

         //public static Test suite() {

         //      TestSuite suite = new TestSuite();

         //      suite.addTest(new XMLTest("testPersonCount"));

         //      suite.addTest(new XMLTest("testContainsPerson"));

         //      return suite;

         //}

 

         /**

          *显示了如何把类的名字传递给测试包构造器来自动装载测试。

          */

        public static Test suite() {

           return new TestSuite(XMLTest.class);

         }

 

         public static void main(String[] args) {

           junit.textui.TestRunner.run(suite());

         }

       }

 

             

 

2.5.4.4.   如何创建测试包?

手工创建与自动创建

 

2.5.5.  TestResult结果类和其它类与接口

TestResult结果类集合了任意测试累加结果,通过TestResult实例传递个每个测试的Run()方法。TestResult在执行TestCase是如果失败会异常抛出

TestListener接口是个事件监听规约,可供TestRunner类使用。它通知listener的对象相关事件,方法包括测试开始startTest(Test test),测试结束endTest(Test test),错误,增加异常addError(Test test,Throwable t)和增加失败addFailure(Test test,AssertionFailedError t)

TestFailure失败类是个“失败”状况的收集类,解释每次测试执行过程中出现的异常情况。其toString()方法返回“失败”状况的简要描述

 

2.6.  Java下的team开发开发模式

1)        采用 cvs(版本控制) + ant(项目管理) + junit(集成测试) 的模式:

2)        每天早上上班,每个开发人员从 cvs server 获取一个整个项目的工作拷贝。

3)        拿到自己的任务,先用 junit 写今天的任务的测试代码。

4)        然后写今天任务的代码,运行测试,直到测试通过,任务完成

5)        在下班前一两个小时,各个开发人员把任务提交到 cvs server

6)        然后由主管对整个项目运行自动测试,哪个测试出错,就找相关人员修改,直到所有测试通过。下班...       

 

2.7.  编写测试类的基本步骤

   使用JUnit编写测试代码的一般步骤是:

2)        引入JUnit框架包。import junit.framework.*

3)        定义测试类名称,一般是将要测试的类名后附加Test

4)        测试类继承JUnitTestCase类。

5)        实现类的构造方法,可以在构造方法中简单的调用super(name)即可。

6)        实现类的main()方法,在main()方法中简单调用junit.textui.TestRunner.run(SimpleTest.class)来指定执行测试类。

7)        重载setUp()tearDown()方法,setUp()方法用于执行每个测试用例时进行环境的初始化工作(比如打开数据库连接),tearDown()方法用于执行每个测试用例后清除环境(比如关闭数据库连接)。

8)        编写每个测试用例,写一些testXXXX()方法(一般是在要测试的方法前附加test)。

 

 

2.8.  Ant 集成?

2.9.  生成 HTML 报告

第3章.     JUnit的扩展

3.1.  HttpUnit

Httpunit则是定义了一个WebConversation,然后针对web形式的responserequest来模拟browser的所有动作以及结果,同样的Httpunit也可以模拟容器内的测试,如servlet的。

我个人认为Httpunit更加从根本上解决了web形式的测试问题,可以说是更加原始的测试,通过requestresponse的形式来模拟整个交互过程,而且还提供了对link的测试,应该来说更加容易让用户真切体会到它的优势所在。反倒是Cactus在测试前就必须通过一大轮配置,更加令我苦恼的是用Cactus很难去模拟一个完整的流程,只能够通过多个test method来不断测试各个servlet method,然后只能证明这些methods没有问题,很难说明这些methods串起来后不出问题。

3.2.  Cactus

Cactus是针对容器内的一种junit扩展,它把TestCase扩展为JSPSevletFilter三种形式,然后通过一些特殊的方法(如beginXXX等)来定义一个测试过程,来模拟一系列交互的容器内测试

 

 

第4章.     JAVA语言测试课程

培训内容 

1 Junit精粹;

2 测试策略;

3 测试组件。

课程大纲

4.1.  第一部分:Junit精粹

1 Junit简介

1.1 安装

1.2 一个简单例子

1.3 理解单元测试框架

1.4 设置JUnit

1.5 利用Junit测试

1.6 总结

2 探索Junit 

2.1 探索Junit核心

2.2 用test runners发起测试

2.3 用TestSuite组成测试

2.4 用TestResult连接参数

2.5 用TestListener注意测试结果

2.6 对测试用例起作用

2.7 通过TestCalculator逐步进阶

2.8 总结

3 取样Junit

3.1 介绍controller组件

3.2 让我们测试它!

3.3 测试异常处理

3.4 建立一个为测试的工程

3.5 总结

4 检查软件测试

4.1 单元测试的需求

4.2 不同种类的测试

4.3 决定测试好的程度

4.4 测试驱动开发

4.5 在开发周期中的测试

4.6 总结

5 自动执行Junit

5.1 在生命中的一天

5.2 从Ant中运行测试

5.3 从Maven中运行测试

5.4 从Eclipse中运行测试

5.5 总结

 

 

4.2.  第二部分:测试策略

6 用桩进行粗的测试

6.1 介绍桩

6.2 练习一个HTTP连接的例子

6.3 web服务器的资源的桩

6.4 对连接进行打桩

6.5 总结

7 mock对象进行隔离测试 7.1 介绍mock对象

7.2 Mock品尝:一个简单例子

7.3 使用mock对象作为一个重构技术

7.4 制作一个HTTP connection的例子

7.5 使用mock作为特洛伊木马

7.6 决定什么时候使用mock对象

7.7 总结

8 Cactus在容器内进行测试

8.1 单元测试组件的问题

8.2 使用mock对象测试组件

8.3 什么是集成单元测试?

8.4 介绍Cactus

8.5 使用Cactus测试组件

8.6 Cactu怎么工作?

8.7 总结

 

4.3.  第三部分:测试组件

9 servlet filter进行单元测试

9.1 呈现管理应用

9.2 用Cactusservlet测试

9.3 使用mock对象测试servlet

9.4 使用Cactus写一个filter测试

9.5 什么时候使用Cactus,什么时候使用mock对象

9.6 总结

10 JSP taglib进行单元测试

10.1 再访管理应用

10.2 什么是JSP单元测试?

10.3 使用Cactus隔离地单元测试一个JSP

10.4 使用Cactus单元测试taglib

10.5 使用mock对象单元测试taglib

10.6 什么时候使用Cactus,什么时候使用mock对象

10.7 总结

11对数据库应用程序进行单元测试

11.1 介绍单元测试数据库

11.2 从数据库中隔离地测试业务逻辑

11.3 从数据库中隔离地测试持续代码

11.4 写数据库集成单元测试

11.5 使用Ant运行Cactus测试

11.6 对构建性能调整

11.7 全面的数据库单元测试策略

11.8 总结

12 EJB进行单元测试

12.1 定义一个例子EJB应用

12.2 使用一个正面的策略

12.3 使用mock对象单元测试JNDI代码

12.4 单元测试session beans

12.5 使用mock对象来测试消息驱动的beans

12.6 使用mock对象来测试实体beans

12.7 选择正确的mock对象策略

12.8 使用集成单元测试

12.9 使用Junit和远程调用

12.10 使用Cactus

12.11 总结

阅读全文
0 0

相关文章推荐

img
取 消
img