2022年junit单元测试教程教程 .pdf

上传人:C****o 文档编号:39733990 上传时间:2022-09-07 格式:PDF 页数:9 大小:94.90KB
返回 下载 相关 举报
2022年junit单元测试教程教程 .pdf_第1页
第1页 / 共9页
2022年junit单元测试教程教程 .pdf_第2页
第2页 / 共9页
点击查看更多>>
资源描述

《2022年junit单元测试教程教程 .pdf》由会员分享,可在线阅读,更多相关《2022年junit单元测试教程教程 .pdf(9页珍藏版)》请在taowenge.com淘文阁网|工程机械CAD图纸|机械工程制图|CAD装配图下载|SolidWorks_CaTia_CAD_UG_PROE_设计图分享下载上搜索。

1、测试的概念长期以来,我所接触的软件开发人员很少有人能在开发的过程中进行测试工作。大部分的项目都是在最终验收的时候编写测试文档。有些项目甚至没有测试文档。现在情况有了改变。我们一直提倡UML、RUP、软件工程、CMM,目的只有一个,提高软件编写的质量。举一个极端的例子:如果你是一个超级程序设计师,一个传奇般的人物。(你可以一边喝咖啡,一边听着音乐,同时编写这操作系统中关于进程调度的模块,而且两天时间内就完成了!)我真得承认,有这样的人。(那个编写UNIX 中的 vi 编辑器的家伙就是这种人。)然而非常遗憾的是这些神仙们并没有留下如何修成正果的README。所以我们这些凡人在同一时间只能将注意力集

2、中到若干点(据科学统计,我并不太相信,一般的人只能同时考虑最多7个左右的问题,高手可以达到12 个左右),而不能既纵览全局又了解细节只能期望于其他的方式来保证我们所编写的软件质量。为了说明我们这些凡人是如何的笨。有一个聪明人提出了软件熵(software entropy)的概念:一个程序从设计很好的状态开始,随着新的功能不断地加入,程序逐渐地失去了原有的结构,最终变成了一团乱麻。你可能会争辩,在这个例子中,设计很好的状态实际上并不好,如果好的话,就不会发生你所说的情况。是的,看来你变聪明了,可惜你还应该注意到两个问题:1)我们不能指望在恐龙纪元(大概是十年前)设计的结构到了现在也能适用吧。2)

3、拥有签字权的客户代表可不理会加入一个新功能是否会对软件的结构有什么影响,即便有影响也是程序设计人员需要考虑的问题。如果你拒绝加入这个你认为致命的新功能,那么你很可能就失去了你的住房贷款和面包(对中国工程师来说也许是米饭或面条,要看你是南方人还是北方人)。另外,需要说明的是我看过的一些讲解测试的书都没有我写的这么有人情味(不好意思.)。我希望看到这片文章的兄弟姐妹能很容易地接受测试的概念,并付诸实施。所以有些地方写的有些夸张,欢迎对测试有深入理解的兄弟姐妹能体察民情,并不吝赐教。好了,我们现在言归正传。要测试,就要明白测试的目的。我认为测试的目的很简单也极具吸引力:写出高质量的软件并解决软件熵这

4、一问题。想象一下,如果你写的软件和Richard Stallman(GNU、FSF 的头儿)写的一样有水准的话,是不是很有成就感?如果你一致保持这种高水准,我保证你的薪水也会有所变动。测试也分类,白箱测试、黑箱测试、单元测试、集成测试、功能测试.。我们先不管有多少分类,如何分类。先看那些对我们有用的分类,关于其他的测试,有兴趣的人可参阅其他资料。白箱测试是指在知道被测试的软件如何(How)完成功能和完成什么样(What)的功能的条件下所作的测试。一般是由开发人员完成。因为开发人员最了解自己编写的软件。本文也是以白箱测试为主。黑箱测试则是指在知道被测试的软件完成什么样(What)的功能的条件下所

5、作的测试。一般是由测试人员完成。黑箱测试不是我们的重点。本文主要集中在单元测试上,单元测试是一种白箱测试。目的是验证一个或若干个类是否按所设计的那样正常工作。集成测试则是验证所有的类是否能互相配合,协同完成特定的任务,目前我们暂不关心它。下面我所提到的测试,除非特别说明,一般都是指单元测试。需要强调的是:测试是一个持续的过程。也就是说测试贯穿与开发的整个过程中,单元测试尤其适合于迭代增量式(iterative and incremental)的开发过程。Martin Fowler(有点儿像引用孔夫子的话)甚至认为:“在你不知道如何测试代码之前,就不应该编写程序。而一旦你完成了程序,测试代码也应

6、该完成。除非测试成功,你不能认为你编写出了可以工作的程序。”我并不指望所有的开发人员都能有如此高的觉悟,这种层次也不是一蹴而就的。但我们一旦了解测试的目的和好处,自然会坚持在开发过程中引入测试。因为我们是测试新手,我们也不理会那些复杂的测试原理,先说一说最简单的:测试就是比较预期的结果是否与实际执行的结果一致。如果一致则通过,否则失败。看下面的例子:名师资料总结-精品资料欢迎下载-名师精心整理-第 1 页,共 9 页 -/将要被测试的类public class Car public int getWheels()return 4;/执行测试的类public class testCar publ

7、ic static void main(String args)testCar myTest=new testCar();myTest.testGetWheels();public testGetWheels()int expectedWheels=4;Car myCar=Car();if(expectedWheels=myCar.getWheels()System.out.println(test Car:getWheels works perfected!);else System.out.println(test Car:getWheels DOESNT work!);如果你立即动手写了

8、上面的代码,你会发现两个问题,第一,如果你要执行测试的类testCar,你必须必须手工敲入如下命令:Windows d:java testCar Unix java testCar 即便测试如例示的那样简单,你也有可能不愿在每次测试的时候都敲入上面的命令,而希望在某个集成环境中(IDE)点击一下鼠标就能执行测试。后面的章节会介绍到这些问题。第二,如果没有一定的规范,测试类的编写将会成为另一个需要定义的标准。没有人希望查看别人是如何设计测试类的。如果每个人都有不同的设计测试类的方法,光维护被测试的类就够烦了,谁还顾得上维护测试类?另外有一点我不想提,但是这个问题太明显了,测试类的代码多于被测试的

9、类!这是否意味这双倍的工作?不!1)不论被测试类Car 的 getWheels 方法如何复杂,测试类testCar 的 testGetWheels 方法只会保持一样的代码量。2)提高软件的质量并解决软件熵这一问题并不是没有代价的。testCar 就是代价。我们目前所能做的就是尽量降低所付出的代价:我们编写的测试代码要能被维护人员容易的读取,我们编写测试代码要有一定的规范。最好IDE 工具可以支持这些规范。好了,你所需要的就是JUnit。一个 Open Source 的项目。用其主页上的话来说就是:“JUnit 是由 Erich Gamma 和 Kent Beck 编写的一个回归测试框架(reg

10、ression testing work)。用于 Java开发人员编写单元测试之用。”所谓框架就是Erich Gamma 和 Kent Beck 定下了一些条条框框,你编写的测试代码必须遵循这个条条框框:继承某个类,实现某个接口。其实也就是我们前面所说的规范。好在JUnit 目前得到了大多数软件工程师的认可。遵循JUnit 我们会得到很多的支持。回归测试就是你不断地对所编写的代码进行测试:编写一些,测试一些,调试一些,然后循环这一过程,你会不断地重复先前的测试,哪怕你正编写其他的类,由于软件熵的存在,你可能在编写第五个类的时候发现,第五个类的某个操作会导致第二个类的测试失败。名师资料总结-精品

11、资料欢迎下载-名师精心整理-第 2 页,共 9 页 -通过回归测试我们抓住了这条大Bug。回归测试框架-JUnit 通过前面的介绍,我们对JUnit 有了一个大概的轮廓。知道了它是干什么的。现在让我们动手改写上面的测试类testCar 使其符合 Junit 的规范能在JUnit 中运行。/执行测试的类(JUnit 版)import junit.work.*;public class testCar extends TestCase protected int expectedWheels;protected Car myCar;public testCar(String name)super(

12、name);protected void setUp()expectedWheels=4;myCar=new Car();public static Test suite()/*the type safe way*TestSuite suite=new TestSuite();suite.addTest(new testCar(Car.getWheels)protected void runTest()testGetWheels(););return suite;*/*the dynamic way*/return new TestSuite(testCar.class);public voi

13、d testGetWheels()assertEquals(expectedWheels,myCar.getWheels();改版后的testCar 已经面目全非。先让我们了解这些改动都是什么含义,再看如何执行这个测试。1import 语句,引入JUnit 的类。(没问题吧)2继承TestCase。可以暂时将一个TestCase看作是对某个类进行测试的方法的集合。详细介绍请参看JUnit 资料3setUp()设定了进行初始化的任务。我们以后会看到setUp 会有特别的用处。名师资料总结-精品资料欢迎下载-名师精心整理-第 3 页,共 9 页 -4testGetWheeels()对预期的值和my

14、Car.getWheels()返回的值进行比较,并打印比较的结果。assertEquals是 junit.work.Assert 中所定义的方法,junit.work.TestCase 继承了 junit.work.Assert。5suite()是一个很特殊的静态方法。JUnit 的 TestRunner 会调用 suite 方法来确定有多少个测试可以执行。上面的例子显示了两种方法:静态的方法是构造一个内部类,并利用构造函数给该测试命名(test name,如 Car.getWheels),其覆盖的runTest()方法,指明了该测试需要执行那些方法testGetWheels()。动态的方法是

15、利用内省(reflection)来实现 runTest(),找出需要执行那些测试。此时测试的名字即是测试方法(test method,如 testGetWheels)的名字。JUnit 会自动找出并调用该类的测试方法。6将 TestSuite看作是包裹测试的一个容器。如果将测试比作叶子节点的话,TestSuite就是分支节点。实际上TestCase,TestSuite以及 TestSuite组成了一个composite Pattern。JUnit 的文档中有一篇专门讲解如何使用Pattern 构造 Junit 框架。有兴趣的朋友可以查看JUnit 资料。如何运行该测试呢?手工的方法是键入如下命

16、令:Windows d:java junit.textui.TestRunner testCar Unix java junit.textui.TestRunner testCar 别担心你要敲的字符量,以后在IDE中,只要点几下鼠标就成了。运行结果应该如下所示,表明执行了一个测试,并通过了测试:.Time:0 OK(1 tests)如果我们将Car.getWheels()中返回的的值修改为3,模拟出错的情形,则会得到如下结果:.F Time:0 There was 1 failure:1)testGetWheels(testCar)junit.work.AssertionFailedErro

17、r:expected:but was:at testCar.testGetWheels(testCar.java:37)FAILURES!Tests run:1,Failures:1,Errors:0 注意:Time 上的小点表示测试个数,如果测试通过则显示OK。否则在小点的后边标上F,表示该测试失败。注意,在模拟出错的测试中,我们会得到详细的测试报告“expected:but was:”,这足以告诉我们问题发生在何处。下面就是你调试,测试,调试,测试.的过程,直至得到期望的结果。Design by Contract(这句话我没法翻译)Design by Contract 本是 Bertran

18、d Meyer(Eiffel 语言的创始人)开发的一种设计技术。我发现在 JUnit 中使用 Design by Contract 会带来意想不到的效果。Design by Contract 的核心是断言(assersion)。断言是一个布尔语句,该语句不能为假,如果为假,则表明出现了一个bug。Design by Contract 使用三种断言:前置条件(pre-conditions)、后置条件(post-conditions)和不变式(invariants)这里不打算详细讨论Design by Contract 的细节,而是希望其在测试中能发挥其作用。前置条件在执行测试之前可以用于判断是否

19、允许进入测试,即进入测试的条件。如expectedWheels 0,myCar!=null。后置条件用于在测试执行后判断测试的结果是否正确。如expectedWheels=myCar.getWheels()。而 不 变 式 在 判 断 交 易(Transaction)的 一 致 性(consistency)方面尤为有用。我希望JUnit 可以将 Design by Contract 作为未来版本的一个增强。名师资料总结-精品资料欢迎下载-名师精心整理-第 4 页,共 9 页 -Refactoring(这句话我依然没法翻译)Refactoring 本来与测试没有直接的联系,而是与软件熵有关,但既

20、然我们说测试能解决软件熵问题,我们也就必须说出解决之道。(仅仅进行测试只能发现软件熵,Refactoring 则可解决软件熵带来的问题。)软件熵引出了一个问题:是否需要重新设计整个软件的结构?理论上应该如此,但现实不允许我们这么做。这或者是由于时间的原因,或者是由于费用的原因。重新设计整个软件的结构会给我们带来短期的痛苦。而不停地给软件打补丁甚至是补丁的补丁则会给我们带来长期的痛苦。(不管怎样,我们总处于水深火热之中)Refactoring 是一个术语,用于描述一种技术,利用这种技术我们可以免于重构整个软件所带来的短期痛苦。当你refactor 时,你并不改变程序的功能,而是改变程序内部的结构

21、,使其更易理解和使用。如:该变一个方法的名字,将一个成员变量从一个类移到另一个类,将两个类似方法抽象到父类中。所作的每一个步都很小,然而12 个小时的Refactoring 工作可以使你的程序结构更适合目前的情况。Refactoring 有一些规则:1 不要在加入新功能的同时refactor 已有的代码。在这两者间要有一个清晰的界限。如每天早上 1-2 个小时的Refactoring,其余时间添加新的功能。2 在你开始Refactoring 前,和 Refactoring 后都要保证测试能顺利通过。否则 Refactoring 没有任何意义。3 进行小的Refactoring,大的就不是Ref

22、actoring 了。如果你打算重构整个软件,就没有必要 Refactoring 了。只有在添加新功能和调试bug 时才又必要Refactoring。不要等到交付软件的最后关头才Refactoring。那样和打补丁的区别不大。Refactoring 用在回归测试中也能显示其威力。要明白,我不反对打补丁,但要记住打补丁是应该最后使用的必杀绝招。(打补丁也需要很高的技术,详情参看微软网站)IDE对 JUnit 的支持目前支持JUnit 的 Java IDE 包括IDE 方式 个人评价(15,满分 5)Forte for Java 3.0 Enterprise Edition plug-in 3 J

23、Builder 6 Enterprise Edition integrated with IDE 4 Visual Age for Java support N/A 在 IDE中如何使用JUnit,是非常具体的事情。不同的 IDE有不同的使用方法。一旦理解了JUnit的本质,使用起来就十分容易了。所以我们不依赖于具体的IDE,而是集中精力讲述如何利用 JUnit 编写单元测试代码。心急的人可参看资料。JUnit 简介既然我们已经对JUnit 有了一个大致的了解,我希望能给大家提供一个稍微正式一些的编写JUnit 测试文档的手册,明白其中的一些关键术语和概念。但我要声明的是这并不是一本完全的手册

24、,只能认为是一本入门手册。同其他OpenSource 的软件有同样的问题,JUnit 的文档并没有商业软件文档的那种有规则,简洁和完全。由开发人员编写的文档总是说不太清楚问题,全整的文档需要参考官方 指南,API 手册,邮件讨论组的邮件,甚至包括源代码中及相关的注释。事实上问题并没有那么复杂,除非你有非常特别的要求,否则,只需参考本文你就可以得到所需的大部分信息。安装名师资料总结-精品资料欢迎下载-名师精心整理-第 5 页,共 9 页 -首先你要获取JUnit 的软件包,从JUnit 下载最新的软件包(截至写作本文时,JUnit 的最新版本是 3.7)。将其在适当的目录下解包。这样在安装目录(

25、也就是你所选择的解包的目录)下你找到一个名为junit.jar 的文件。将这个jar 文件加入你的CLASSPATH 系统变量。(IDE的设置会有所不同,参看你所喜爱的IDE的配置指南)JUnit 就安装完了。太easy 了!你一旦安装完JUnit,就有可能想试试我们的Car 和 testCar 类,没问题,我已经运行过了,你得到的结果应该和我列出的结果类似。(以防新版JUnit 使我的文章过时)接下来,你可能会先写测试代码,再写工作代码,或者相反,先写工作代码,再写测试代码。我更赞成使用前一种方法:先写测试代码,再写工作代码。因为这样可以使我们编写工作代码时清晰地了解工作类的行为。要注意编写

26、一定能通过的测试代码(如文中的例子)并没有任何意义,只有测试代码能帮助我们发现bug,测试代码才有其价值。此外测试代码还应该对工作代码进行全面的测试。如给方法调用的参数传入空值、错误值和正确的值,看看方法的行为是否如你所期望的那样。你现在已经知道了编写测试类的基本步骤:1扩展 TestCase类;2覆盖 runTest()方法(可选);3写一些 testXXXXX()方法;Fixture 解下来的问题是,如果你要对一个或若干个的类执行多个测试,该怎么办?JUnit 对此有特殊的解决办法。如果需要在一个或若干个的类执行多个测试,这些类就成为了测试的context。在 JUnit 中被称为 Fix

27、ture(如 testCar 类中的myCar 和 expectedWheels)。当你编写测试代码时,你会发现你花费了很多时间配置/初始化相关测试的Fixture。将配置 Fixture 的代码放入测试类的构造方法中并不可取,因为我们要求执行多个测试,我并不希望某个测试的结果意外地(如果这是你要求的,那就另当别论了)影响其他测试的结果。通常若干个测试会使用相同的Fixture,而每个测试又各有自己需要改变的地方。为此,JUnit 提供了两个方法,定义在TestCase类中。protected void setUp()throws java.lang.Exception protected v

28、oid tearDown()throws java.lang.Exception 覆盖 setUp()方法,初始化所有测试的Fixture(你甚至可以在setUp 中建立网络连接),将每个测试略有不同的地方在testXXX()方法中进行配置。覆盖 tearDown()(我总想起一首叫雨滴的吉他曲),释放你在setUp()中分配的永久性资源,如数据库连接。当 JUnit 执行测试时,它在执行每个testXXXXX()方法前都调用setUp(),而在执行每个testXXXXX()方法后都调用tearDown()方法,由此保证了测试不会相互影响。TestCase 需要提醒一下,在 junit.wor

29、k.Assert 类中定义了相当多的assert 方法,主要有 assert(),assert(),assertEquals(),assertNull(),assertSame(),assertTrue(),fail()等方法。如果你需要比较自己定义的类,如 Car。assert 方法需要你覆盖Object 类的 equals()方法,以比较两个对象的不同。实践表明:如果你覆盖了Object 类的 equals()方法,最好也覆盖Object 类的 hashCode()方法。再进一步,连带Object 类的 toString()方法也一并覆盖。这样可以使测试结果更具可读性。当你设置好了Fixt

30、ure 后,下一步是编写所需的testXXX()方法。一定要保证testXXX()方法的public 属性,否则无法通过内省(reflection)对该测试进行调用。名师资料总结-精品资料欢迎下载-名师精心整理-第 6 页,共 9 页 -每个扩展的TestCase类(也就是你编写的测试类)会有多个testXXX()方法。一个testXXX()方法就是一个测试。要想运行这个测试,你必须定义如何运行该测试。如果你有多个testXXX()方法,你就要定义多次。JUnit 支持两种运行单个测试的方法:静态的和动态的方法。静态的方法就是覆盖TestCase类的 runTest()方法,一般是采用内部类的

31、方式创建一个测试实例:TestCase test01=new testCar(test getWheels)public void runTest()testGetWheels();采用静态的方法要注意要给每个测试一个名字(这个名字可以任意起,但你肯定希望这个名字有某种意义),这样你就可以区分那个测试失败了。动态的方法是用内省来实现runTest()以创建一个测试实例。这要求测试的名字就是需要调用的测试方法的名字:TestCase test01=new testCar(testGetWheels);JUnit 会动态查找并调用指定的测试方法。动态的方法很简洁,但如果你键入了错误的名字就会得到一

32、个令人奇怪的NoSuchMethodException 异常。动态的方法和静态的方法都很好,你可以按照自己的喜好来选择。(先别着急选择,后面还有一种更酷的方法等着你呢。)TestSuite 一旦你创建了一些测试实例,下一步就是要让他们能一起运行。我们必须定义一个TestSuite。在 JUnit 中,这就要求你在TestCase类中定义一个静态的suite()方法。suite()方法就像main()方法一样,JUnit 用它来执行测试。在suite()方法中,你将测试实例加到一个TestSuite对象中,并返回这个TestSuite对象。一个 TestSuite对象可以运行一组测试。TestS

33、uite和 TestCase都实现了Test 接口(interface),而Test 接口定义了运行测试所需的方法。这就允许你用TestCase和 TestSuite的组合创建一个TestSuite。这就是为什么我们前面说TestCase,TestSuite以及 TestSuite组成了一个composite Pattern 的原因。例子如下:public static Test suite()TestSuite suite=new TestSuite();suite.addTest(new testCar(testGetWheels);suite.addTest(new testCar(te

34、stGetSeats);return suite;从 JUnit 2.0 开始,有一种更简单的动态定义测试实例的方法。你只需将类传递给TestSuite,JUnit 会根据测试方法名自动创建相应的测试实例。所以你的测试方法最好取名为testXXX()。例子如下:public static Test suite()return new TestSuite(testCar.class);从 JUnit 的设计我们可看出,JUnit 不仅可用于单元测试,也可用于集成测试。关于如何用JUnit进行集成测试请参考相关资料。为了兼容性的考虑,下面列出使用静态方法的例子:public static Test

35、 suite()TestSuite suite=new TestSuite();名师资料总结-精品资料欢迎下载-名师精心整理-第 7 页,共 9 页 -suite.addTest(new testCar(getWheels)protected void runTest()testGetWheels(););suite.addTest(new testCar(getSeats)protected void runTest()testGetSeats(););return suite;TestRunner 有了 TestSuite我们就可以运行这些测试了,JUnit 提供了三种界面来运行测试Tex

36、t UI junit.textui.TestRunner AWT UI junit.awtui.TestRunner Swing UI junit.swingui.TestRunner 我们前面已经看过文本界面了,下面让我们来看一看图形界面:界面很简单,键入类名testCar。或在启动UI 的时候键入类名:Windows d:java junit.swingui.TestRunner testCar Unix java junit.swingui.TestRunner testCar 从图形 UI 可以更好的运行测试可查单测试结果。还有一个问题需要注意:如果 JUnit 报告了测试没有成功,J

37、Unit 会区分失败(failures)和错误(errors)。失败是一个期望的被assert方法检查到的结果。而错误则是意外的问题引起的,如ArrayIndexOutOfBoundsException。由于 TestRunner十分简单,界面也比较直观,故不多介绍。朋友们可自行参考相关资料。JUnit 最佳实践Martin Fowler(又是这位高人)说过:“当你试图打印输出一些信息或调试一个表达式时,写一些测试代码来替代那些传统的方法。”一开始,你会发现你总是要创建一些新的Fixture,而且测试似乎使你的编程速度慢了下来。然而不久之后,你会发现你重复使用相同的Fixture,而且新的测试

38、通常只涉及添加一个新的测试方法。你可能会写许多测试代码,但你很快就会发现你设想出的测试只有一小部分是真正有用的。你所需要的测试是那些会失败的测试,即那些你认为不会失败的测试,或你认为应该失败却成功的测试。我们前面提到过测试是一个不会中断的过程。一旦你有了一个测试,你就要一直确保其正常工作,以检验你所加入的新的工作代码。不要每隔几天或最后才运行测试,每天你都应该运行一下测试代码。这种投资很小,但可以确保你得到可以信赖的工作代码。你的返工率降低了,你会有更多的时间编写工作代码。不要认为压力大,就不写测试代码。相反编写测试代码会使你的压力逐渐减轻,应为通过编写测试代码,你对类的行为有了确切的认识。你

39、会更快地编写出有效率地工作代码。下面是一些具体的编写测试代码的技巧或较好的实践方法:1.不要用 TestCase的构造函数初始化Fixture,而要用 setUp()和 tearDown()方法。2.不要依赖或假定测试运行的顺序,因为 JUnit 利用 Vector 保存测试方法。所以不同的平台名师资料总结-精品资料欢迎下载-名师精心整理-第 8 页,共 9 页 -会按不同的顺序从Vector 中取出测试方法。3.避免编写有副作用的TestCase。例如:如果随后的测试依赖于某些特定的交易数据,就不要提交交易数据。简单的会滚就可以了。4.当继承一个测试类时,记得调用父类的setUp()和 te

40、arDown()方法。5.将测试代码和工作代码放在一起,一边同步编译和更新。(使用 Ant 中有支持junit 的 task.)6.测试类和测试方法应该有一致的命名方案。如在工作类名前加上test 从而形成测试类名。7.确保测试与时间无关,不要依赖使用过期的数据进行测试。导致在随后的维护过程中很难重现测试。8.如果你编写的软件面向国际市场,编写测试时要考虑国际化的因素。不要仅用母语的Locale 进行测试。9.尽可能地利用JUnit 提供地 assert/fail 方法以及异常处理的方法,可以使代码更为简洁。10.测试要尽可能地小,执行速度快。事实上,JUnit 还可用于集成测试,但我并没涉及

41、到,原因有两个:一是因为没有单元测试,集成测试无从谈起。我们接受测试地概念已经很不容易了,如果再引入集成测试就会更困难。二是我比较懒,希望将集成测试的任务交给测试人员去做。在JUnit 的网站上有一些相关的文章,有空大家可以翻一翻。JUnit 与 J2EE 如果大家仔细考虑一下的话,就会发现,JUnit 有自己的局限性,比如对图形界面的测试,对 servlet/JSP 以及 EJB 的测试我们都没有举相关的例子。实际上,JUnit 对于GUI 界面,servlet/JSP,JavaBean以及 EJB都有办法测试。关于GUI 的测试比较复杂,适合用一整篇文章来介绍。这里就不多说了。前面我们所做

42、的测试实际上有一个隐含的环境,JVM 我们的类需要这个JVM 来执行。而在J2EE框架中,servlet/JSP,EJB都要求有自己的运行环境:Web Container 和 EJB Container。所以,要想对 servlet/JSP,EJB进行测试就需要将其部署在相应的Container 中才能进行测试。由于 EJB不涉及 UI 的问题(除非EJB操作 XML 数据,此时的测试代码比较难写,有可能需要你比较两棵DOM 树是否含有相同的内容)只要部署上去之后就可以运行测试代码了。此时 setUp()方法显得特别有用,你可以在 setUp()方法中利用JNDI查找特定的EJB。而在 tes

43、tXXX()方法中调用并测试这些EJB的方法。这里所指的JavaBean同样没有 UI 的问题,比如,我们用 JavaBean来访问数据库,或用 JavaBean来包裹 EJB。如果这类JavaBean没有用到Container 的提供的服务,则可直接进行测试,同我们前面所说的一般的类的测试方法一样。如果这类JavaBean用到了 Container 的提供的服务,则需要将其部署在Container 中才能进行测试。方法与EJB类似。对 于servlet/JSP 的 测 试 则 比 较 棘 手,有 人 建 议 在 测 试 代 码 中 构 造HttpRequest和HttpResponse,然后

44、进行比较,这就要求开发人员对HTTP协议以及servlet/JSP 的内部实现有比较深的认识。我认为这招不太现实。也有人提出使用HttpUnit。由于我对Cactus 和HttpUnit 了解不多,所以无法做出合适的建议。希望各位先知们能不吝赐教。正是由于JUnit 的开放性和简单易行,才会引出这篇介绍文章。但技术总在不断地更新,而且我对测试并没有非常深入的理解;我可以将一个复杂的概念简化成一句非常容易理解的话。但我的本意只是希望能降低开发人员步入测试领域的门槛,而不是要修改或重新定义一些概念。这一点是特别要强调的。最后,如果有些兄弟姐妹能给我指出一些注意事项或我对某些问题的理解有误,我会非常感激的。名师资料总结-精品资料欢迎下载-名师精心整理-第 9 页,共 9 页 -

展开阅读全文
相关资源
相关搜索

当前位置:首页 > 教育专区 > 高考资料

本站为文档C TO C交易模式,本站只提供存储空间、用户上传的文档直接被用户下载,本站只是中间服务平台,本站所有文档下载所得的收益归上传人(含作者)所有。本站仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。若文档所含内容侵犯了您的版权或隐私,请立即通知淘文阁网,我们立即给予删除!客服QQ:136780468 微信:18945177775 电话:18904686070

工信部备案号:黑ICP备15003705号© 2020-2023 www.taowenge.com 淘文阁