• jdbcfor2005 > JBuilder 2005 单元测试体验
  • JBuilder 2005 单元测试体验

    免费下载 下载该文档 文档格式:DOC   更新时间:2006-03-02   下载次数:0   点击次数:1
    文档基本属性
    文档语言:Simplified Chinese
    文档格式:doc
    文档作者:jelly
    关键词:
    主题:
    备注:
    点击这里显示更多文档属性
    JBuilder 2005 单元测试体验
    白盒测试是软件工程中重要的概念,开发人员往往要花1/3时间测试自己编写的程序.一个类所有开放的API接口都必须通过白盒测试,JBuilder集成了目前流行的JUnit单元测试框架,提供了创建,运行,编译测试用例的支持.
    自动测试代码的重要性
    一个产品只有通过检验才能投放市场,同样的,一个业务类也只有在经验测试后才能保证功能的正确性,以便被其他类或程序调用,否则隐藏其中的Bug就蔓延开了.业务功能点测试是测试人员的职责,但业务类API的正确性必须由开发人员保证.
    一个产品只有通过检验才能投放市场,同样的,一个业务类也只有在经验测试后才能保证功能的正确性,以便被其他类或程序调用,否则隐藏其中的Bug就蔓延开了.业务功能点测试是测试人员的职责,但业务类API的正确性必须由开发人员保证.
    回忆一下最近你所开发的系统,往往一个最难忘的情节是通宵达旦地毯式搜索某个刁专的Bug,历尽千辛万苦,最终找到并解决了它.查找一个隐藏的Bug往往是踏破铁蹄无觅处,而找到后却是:解决全不费功夫.
    造成这尴尬窘局有以下几点原因:
    其一是使用增量式测试策略,即先编写功能代码,在模块开发完毕后才回过头来编写测试用例,因为一个功能模块可能包含许多相互关联的类,形成了层层调用,交错复杂的调用网络,一旦发现了Bug,只得查户口似的逐一排查,其艰辛程度可想而知.
    其二是使用不正确的测试方法,如在每个类中提供一个main()测试函数,对类中的功能方法进行测试,通过运行类的main()方法查看类功能的正确性.在某种程序上,这或许是一个值得赞扬的工作习惯,但工作方式却不足取.因为每个类都必须单独运行,以执行其测试功能,并由开发人员观察测试的正确性.随着程序规模的扩大,类数目直线上升,原有的类也会发生代码的调整,一些功能点可能就变成了漏网之鱼,变成了茫茫"类"海里的黑户口,将来"违法乱纪"起来就很难监控了.
    针对这些传统测试思想的不足,测试先行,频繁测试,自动测试的测试思想被越来越多的开发人员所接受并付诸实践.
    测试先行乍听起来有点让人不可思议,一件东西还没有做出来就想着怎么去测试它 仔细分析,这并不荒唐,因为这让你在设计类时,站在调用者的角度去理解类的对外接口,迫使你深入理解类的外在关系,考虑接口的用途,而在具体编写程序时才去具体考虑内部实现细节,这样设计出接口将更易使用,结构也会更趋合理.
    频繁测试,即指测试不应当是阶段性的工作,而应当在程序编写过程中不断进行.因为系统中的类之间往往都存在较多的关联关系,当更改了类的功能时,往往会有多个类受到直接或间接的影响.所以你应该频繁测试以及早发现这种因功能,调整而引起的Bug,越早发现错误解决它的代价越小.频繁测试也是XP编程的一个重要环节,XP编程总让人觉得他们注重功能实现而忽视测试,其实他们也非常关注测试,毕竟测试可以使他们尽可能快的稳步前进.
    所谓自动测试并不是说有一个工具可以让你像安检器一样,自动测试出你类中的问题.而是指应用一定的测试框架,为每个业务类编写独立的测试用例,类代码调整后,对应的测试用例同步调整.多个测试用例组成一个测试套件一起批量运行,它们就像一个强大的Bug嗅探器,一旦发现Bug就会输出特定的信息报告错误,只要一个测试用例没有通过测试就说明程序中有问题.测试用例中所包含的测试规则完成由你定制,这个测试套件对Bug嗅探的"灵敏度"完全取决于测试用例的测试规则,框架提供编写和运行测试用例的规范性方法.
    在编写一个业务类时,需要相应编写对应的测试用例,一开始挺招"惯性定律"抵触的,因为它要求你将创建一个测试用例类,似乎需要更多的工作.但你的付出是会得到加倍回报的,随着软件类规模的增大你会发现,当传统测试方法越来越捉襟见肘,穷于应付时,基于测试框架的测试技术依然"谈笑自如".当然别人这么说,我们也不应当马上就深信不疑,疑惑永远是值得推崇的科学精神,我们应该通过自己的实践却真真切切地体会这种改进所带来的快乐.
    JUnit测试框架
    JUnit是由Erich Gamma和Kent Beck开发的开源测试框架,JBuilder集成了这个框架并做了扩展.JUnit之所以流行并为广大的开发人员所推崇,一是它实战性强,功能强大,二是它实在简单.一个产品或框架要能有生命力,最好都具备这样的特点.
    简单的框架
    JUnit是由Erich Gamma和Kent Beck开发的开源测试框架,JBuilder集成了这个框架并对此做了扩展.JUnit之所以流行并为广大的开发人员所推崇,一是因为它实战性强,功能强大,二是因为它实在简单.一个产品或框架要能有生命力,最好都具备这样的特点.
    简单地讲这个框架提供了许多断言(assert)方法,允许你设置测试的规则,如:assertEquals(),assertNull(),assertNotSame(),assertTrue()等方法,一个测试用例包括了多个断言,当运行测试用例后,JUnit运行器会报告哪些断言没有通过,开发人员就可顺藤摸瓜搞个水落石出了.而传统的测试方法需要将期望的结果用诸如System.out.println()等语句将过程信息打印到控制台或日志中,由开发人员观察输出信息以判断是否正确,现在这种"观察"的工作由JUnit的那些assertXxx()方法自动完成.
    JUnit的测试框架类结构很简单,主要由3个类组成,其类图关系如下图所示:
    图 错误!文档中没有指定样式的文字.JUnit测试框架类结构
    ·junit.framework.Test:测试接口.
    ·junit.framework.TestCase:测试用例类,业务类的测试用例类只需要承继这个TestCase,根据情况编写若干个public void testXxx()方法,在方法中通过assertYyy()定制若干测试规则就可以了.
    ·junit.framework.TestSuite:测试套件类,它可以将多个测试用例类捆绑在一起运行,也可以捆绑另一个测试套件.
    测试固件(Fixture)
    一个测试用例可以包含若干个testXxx()测试方法,测试用例测试一个或多个类API接口的正确性,当然在调用类API时,需要事先创建这个类的对象及一些关联的对象,这组对象就称为测试固件(Fixture),相当于测试用例的"工作对象".
    我们在前面说过,一个测试用例类可以包含多个testXxx()方法,在运行时,每个测试方法都对应一个测试用例类的实例.当然,你可以在具体的testXxx()方法里声明并实例化业务类的实例,在测试完成后再销毁它们.但是,这么一来你就要在每个testXxx()方法中都重复这些代码,因为TestCase实例被运行时,依照以下步骤运行:
    1.创建测试用例的实例.
    2.调用setUp()方法,执行一些初始化工作.
    3.运行testXxx()测试方法.
    4.调用tearDown()方法,执行销毁对象的工作.
    如果测试用例类中有多个testXxx()方法,且它们都需要使用到相同的一组对象,我们可以在setUp()中实例化这组对象,并在tearDown()中销毁它们.要编写测试固件,依照以下步骤进行:
    1.创建TestCase类的子类.
    2.在子类中声明若干个测试所用的对象.
    3.覆盖setUp()方法,在方法中实例化这些对象.
    4.覆盖tearDown()方法,释放这些对象的资源.
    如下面即是一个简单的测试固件:
    代码清单 错误!文档中没有指定样式的文字.测试固件
    1. public class MoneyTest extends TestCase
    2. {
    3. private Money f12CHF;//12瑞士法郎
    4. private Money f14CHF; //14瑞士法郎
    5. private Money f28USD; //28美国美元
    6. protected void setUp() {
    7. f12CHF= new Money(12, "CHF");
    8. f14CHF= new Money(14, "CHF");
    9. f28USD= new Money(28, "USD");
    10. }
    11. protected void tearDown(){}
    12. }
    第3~5行声明了3个Money类对象(测试固件),在setUp()方法中实例化这3个对象(第7~9行),由于这些对象可以被垃圾进行直接回收,所以在tearDown()中不做任何操作.
    测试用例(TestCase)
    有了测试固件,就可以开始编写测试用例的测试方法了.当然你也可不需要测试固件而直接编写测试用例方法.下面我们在测试固件的基础上添加测试用例方法testMoneyBag(),代码如下所示:
    代码清单测试用例方法
    1. public class MoneyTest extends TestCase
    2. {
    3. private Money f12CHF;//12瑞士法郎
    4. private Money f14CHF; //14瑞士法郎
    5. private Money f28USD; //28美国美元
    6. protected void setUp() {
    7. f12CHF= new Money(12, "CHF");
    8. f14CHF= new Money(14, "CHF");
    9. f28USD= new Money(28, "USD");
    10. }
    11. public void testMoneyBag()
    12. {
    13. Money bag[]= { f26CHF, f28USD };
    14. MoneyBag expected= new MoneyBag(bag);
    15. assertEquals(expected, f12CHF.add(f28USD.add(f14CHF)));
    16. }
    17. protected void tearDown(){}
    18. }
    测试方法都必须以test为前缀,且必须是public void的,运行器以此为反射查找规则找到这些测试用例方法.在一个方法中可以包括多个assertYyy()方法,每个assertYyy()方法都是一个测试规则.像第15行的assertYyy()断言方法即为测试Money的add()方法和MoneyBag类正确性的测试规则.
    你可以在MoneyTest中添加多个public void testXxx()方法,运行器为每个方法生成一个测试用例实例,分别运行.
    测试套件(TestSuite)
    如果每次只能运行一个测试用例,那么又陷入了我们前面所谈到的传统测试的窘境:手工去运行一个个测试用例,测试套件专门为解决这一问题而来.它通过TestSuite对象将多个测试用例组装成到一个测试套件,则测试套件批量运行.需要特殊指出的是,可以把一个测试套件整个添加到另一个测试套件中,就象小筐装进大筐里变成一个箧一样.
    测试套件类也通过承继TestCase类实现,只不过它提供了一个public static Test suite()静态方法,在该方法中将多个测试用例捆绑组装在一起.一个典型的测试套件代码如下所示:
    代码清单 错误!文档中没有指定样式的文字.测试套件
    1. public class MoneyTestSuite extends TestCase
    2. {
    3. public TestSuite1(String s)
    4. {
    5. super(s);
    6. }
    7. public static Test suite()
    8. {
    9. TestSuite suite = new TestSuite();
    10. suite.addTestSuite(MoneyTest.class);
    11. suite.addTestSuite(MoneyBag.class);
    12. return suite;
    13. }
    14. }
    在第9行中声明并实例化了一个TestSuite,在第10,11行分别加入一个测试用例.你可以通过suite.addTest(Test t)方法添加一个套件.这样运行这个套件就可以自动运行所有测试用例的测试方法了.
    测试运行器
    JUnit提供了3个标准的测试运行器运行这些测试用例或测试套件,这3个测试运行器分别是:
    ·junit.textui.TestRunner:文本测试运行器.
    ·junit.awtui.TestRunner:使用AWT组件界面的测试运行器.
    ·junit.swingui.TestRunner:使用Swing组件界面的测试运行器.
    下面是基于AWT组件的测试运行器,如下图所示:
    图 错误!文档中没有指定样式的文字.AWT测试运行器
    ·Test class name:指定测试用例类和测试套件类.
    ·一个进度条:表示运行测试的执行进度,进度条下是正确,错误,失败的测试统计数.
    ·Error and Failures:列出了测试错误和失败的列表,点选其中的一个选项时,JUnit在窗口底部列出错误跟踪迹.
    提示:
    JBuilder提供了方便的运行测试用例和测试套件类的方法,你只须点击鼠标右键就可直接调用了.此外,JBuilder提供了一个JBTestRunner测试运行器,在功能和易用性上非JUnit提供的测试运行器所能媲美.JBuilder支持JUnit所提供的两个测试运行器:junit.textui.TestRunner和junit.swingui.TestRunner.
    业务类介绍
    为了便于讲解,拟通过两个简单的业务类引出测试用例,一个是分段函数类,另一个是字符串处理类,在这节里我们先来熟悉这两个业务类.
    为了便于讲解,拟通过两个简单的业务类引出测试用例,一个是分段函数类,另一个是字符串处理类,在这节里我们先来熟悉这两个业务类.
    分段函数类
    分段函数Subsection类有两个函数,sign()是一个符号函数,而getValue(int d)函数功能如下:
    当d < -2时,值为abs(d);
    当-2≤d<2 且d!=0时,值为d*d;
    当d=0时,值为100;
    当2≤d时,值为d*d*d.
    其代码如下图所示:
    代码清单 错误!文档中没有指定样式的文字.分段函数
    1. package chapter25;
    2.
    3. public class Subsection
    4. {
    5. public static int getValue(int d) {
    6. if (d == 0) {
    7. return 100;
    8. } else if (d = -2 && d = 2
    13. // if (d > 32) {
    14. // return Integer.MAX_VALUE;
    15. // }
    16. return d * d * d;
    17. }
    18. }
    19.
    20. public static int sign(double d) {
    21. if (d 0) {
    24. return 1;
    25. } else {
    26. return 0;
    27. }
    28. }
    29. }
    在getValue()方法中,当d>32时,d*d*d的值将超过int数据类型的最大值(32768),所以当d>32时,理应做特殊的处理,这里我们特意将这个特殊处理的代码注释掉(第13~15行),模拟一个潜在的Bug.
    字符串处理类
    由于标准JDK中所提供的String类对字符串操作功能有限,而字符串处理是非常常用的操作,所以一般的系统都提供了一个自己的字符串处理类.下面就是一个字符串处理类,为了简单,我们仅提供了一个将字符串转换成数组的方法string2Array(),其代码如下所示:
    代码清单 错误!文档中没有指定样式的文字.字符串处理类
    1. package chapter25;
    2. public class StringUtils
    3. {
    4. public static String[] string2Array(String str, char splitChar, boolean trim) {
    5. if (str == null) {
    6. return null;
    7. } else {
    8. String tempStr = str;
    9. int arraySize = 0; //数组大小
    10. String[] resultArr = null;
    11. if (trim) { //如果需要删除头尾多余的分隔符
    12. tempStr = trim(str, splitChar);
    13. }
    14. arraySize = getCharCount(tempStr, splitChar) + 1;
    15. resultArr = new String[arraySize];
    16. int fromIndex = 0, endIndex = 0;
    17. for (int i = 0; i < resultArr.length; i++) {
    18. endIndex = tempStr.indexOf(splitChar, fromIndex);
    19. if (endIndex == -1) {
    20. resultArr[i] = tempStr.substring(fromIndex);
    21. break;
    22. }
    23. resultArr[i] = tempStr.substring(fromIndex, endIndex);
    24. fromIndex = endIndex + 1;
    25. }
    26. return resultArr;
    27. }
    28. }
    29.
    30. //将字符串前面和后面的多余分隔符去除掉.
    31. private static String trim(String str, char splitChar) {
    32. int beginIndex = 0, endIndex = str.length();
    33. for (int i = 0; i 0; i--) {
    40. if (str.charAt(i - 1) != splitChar) {
    41. endIndex = i;
    42. break;
    43. }
    44. }
    45. return str.substring(beginIndex, endIndex);
    46. }
    47.
    48. //计算字符串中分隔符中个数
    49. private static int getCharCount(String str, char splitChar) {
    50. int count = 0;
    51. for (int i = 0; i < str.length(); i++) {
    52. if (str.charAt(i) == splitChar) {
    53. count++;
    54. }
    55. }
    56. return count;
    57. }
    58. }
    除对外API string2Array()外,类中还包含了两个支持方法.trim()负责将字符前导和尾部的多余分隔符删除掉(第31~46行);而getCharCount()方法获取字符中包含分隔符的数目,以得到目标字符串数组的大小(第49~57行).
    创建测试用例
    JBuilder为测试用例类指定了一个默认的类名,即Test,包名和业务类包名一致.接受默认的值,直接按Finish创建TestSubsection测试用例类.
    我们先为Subsection类创建测试用例.
    1.在编辑器中打开Subsection.java文件,使其处理激活态.
    2.File->New...->Test->在Test页的对象库中双击Test Case图标,启动创建测试用例的向导,如下图所示:
    图 错误!文档
    中没有指定样式的文字.指定测试的方法
    ·Select class:测试的目标类,默认为当前编辑器中打开的类,也可以通过其后的…按钮选择工程中其他的类.
    ·Avaiable methods:列出了测试目标类的所有public,protected和默认可视域的方法,private方法不列出.只要你测试了前三者的方法,private也被间接测试到了.这里,我们选择getValue()和sign()方法.
    点击Next到下一步.
    3.设置测试用例类的类名.
    图 错误!文档中没有指定样式的文字.指定测试用例类的名称
    JBuilder为测试用例类指定了一个默认的类名,即Test,包名和业务类包名一致.接受默认的值,直接按Finish创建TestSubsection测试用例类.
    实战经验:
    虽然在物理上,业务类和测试用例类被放在不同目录下,但在工程窗格的资源树中,业务类和测试用例还是挤在了一起.如果一个包下有多个业务类,加上它们相应的测试用例类,将显得更加拥挤不堪.所以最好将测试用例放到不同的包中,如com.super.bdbj包中的所有业务类的测试用例放到test.super.bdbj目录下,这样将彻底解决测试用例和业务类的物理和逻辑上的分离,使工程窗格中的资源树更加整洁明了.
    TestSubsection类的代码如下所示:
    代码清单 错误!文档中没有指定样式的文字.向导生成的TestSubsection类
    1. package chapter25;
    2.
    3. import junit.framework.*;
    4. public class TestSubsection extends TestCase {
    5. private Subsection subsection = null;
    6. protected void setUp() throws Exception {
    7. super.setUp();
    8. subsection = new Subsection();
    9. }
    10.
    11. protected void tearDown() throws Exception {
    12. subsection = null;
    13. super.tearDown();
    14. }
    15.
    16. public void testGetValue() {
    17. int d = 0;
    18. int expectedReturn = 0;
    19. int actualReturn = subsection.getValue(d);
    20. assertEquals("return value", expectedReturn, actualReturn);
    21. /**@todo fill in the test code*/
    22. }
    23.
    24. public void testSign() {
    25. double d = 0.0;
    26. int expectedReturn = 0;
    27. int actualReturn = subsection.sign(d);
    28. assertEquals("return value", expectedReturn, actualReturn);
    29. /**@todo fill in the test code*/
    30. }
    31. }
    在第5行声明了一个Subsection的成员变量,并在setUp()中实例化这个变量(第7行),在tearDown()中释放这个变量(第12行),其实这三部分就构成了一个测试固件.当然,由于我们的getValue(),sign()方法都是静态方法,所以并不需要这个固件,在测试方法中直接调用方法就可以了,如Subsection.getValue(),但为了加强概念上的认识,我们特别予以保留.
    第16~22行的testGeValue()方法,和第24~30行的testSign(),就是在向导第1步所选择的需要测试的API方法对应的测试方法.JBuilder当然不可能知道我们API的逻辑规则,所以它仅提供了一个框架式的测试代码,需要我们发挥聪明才智通过assertXxx()定制覆盖性强的测试规则.
    注意:
    你也可以手工在TestSubsection类中添加测试方法,测试方法必须遵照public void testXxx()样式规范.所以如果你想在测试用例类中添加一个辅助性的方法,请不要以test为前缀,在更改业已生成的测试方法名称时,也要保证不去除方法前的test前缀,测试运行器籍此查找测试用例类中的测试方法.
    下面,分别删除testGetValue()和testSign()方法体中的代码,用以下粗体代码替换之:
    代码清单 错误!文档中没有指定样式的文字.添加测试规则后的TestSubsection类
    1. …
    2. public class TestSubsection extends TestCase
    3. {
    4. …
    5. public void testGetValue() {
    6. int d1 = -3,y1 = 3;
    7. int d2 = -2,y2 = 4;
    8. int d3 = 0 ,y3 = 100;
    9. int d4 = 2 ,y4 = 8;
    10. int d5 = 33 ,y5 = 32768;
    11. int d6 = 33 ,y6 = Integer.MAX_VALUE;
    12. assertEquals(y1,subsection.getValue(d1));
    13. assertEquals(y2,subsection.getValue(d2));
    14. assertEquals(y3,subsection.getValue(d3));
    15. assertEquals(y4,subsection.getValue(d4));
    16. assertEquals(y5,subsection.getValue(d5));
    17. assertEquals(y6,subsection.getValue(d6));
    18. }
    19.
    20. public void testSign() {
    21. double d1 = -1.0, d2 = 0.0, d3 = 1.0;
    22. int y1 = 1, y2 = 0, y3 = 1;
    23. assertEquals(y1, subsection.sign(d1));
    24. assertEquals(y1, subsection.sign(d1));
    25. assertEquals(y1, subsection.sign(d1));
    26. }
    27. }
    打蛇打七寸,擒贼先擒王,抓Bug还须在那些关键点上下功夫,特殊转换点是最容易出现问题的热点地区,需要给予特别的关注.所以我们为getValue()设置了6个测试点,而为sign()方法设置了3个测试点.
    在工程窗格资源树中找到TestSubsection.java文件,右击在弹出的菜单中选择Run Test using "TestSubsection1",JBuilder利用JBTestRunner测试运行器运行这个测试用例,在信息窗格中出现如下的运行器界面:
    图 错误!文档中没有指定样式的文字.JBTestRunner运行器界面
    JBTestRunner窗口左边为3个标签页,它们的作用在卤淼乃得鳎 BR>
    表 错误!文档中没有指定样式的文字.JBTestRunner窗口标签页说明
    标签页图标
    说明

    如果测试没有错误,该标签页为默认显示的标签页.形成一棵测试套件->测试用例->测试方法3级的级联树.树中每个节点均有一个状态指示图标. 表示通过测试,而 表示未通过测试.点击未通过测试的节点,右边帧列出了错误跟踪迹,通过这个跟踪迹可以找到哪个测试规则(断言方法assertXxx())未通过.

    测试错误页,如果发生了测试错误,该页被默认显示.列出所有发生错误的测试,该页是 标签页的子集.

    该标签页中显示出所有输出到控制台的信息,如测试用例中有通过System.out.println()输出信息,则这些信息在此查看.
    当没有发生失败的测试时,测试进度条显示为绿色,否则显示为红色.对于测试用例很少的情况你看不到它的效果,如果成百上千的测试用例一起运行,这个进度条的作用是显而易见了.进度条右边是测试结果统计信息:包括测试方法总数和成功数,统计信息右边是测试所花费的时间.
    右帧是测试失败的引发点,单击链接,JBuilder自动定位到测试用例测试失败的地方,在本例里,JBuilder将定位到代码清单 错误!文档中没有指定样式的文字.添加测试规则后的TestSubsection类的代码的第17行,即:assertEquals(y5, subsection.getValue(d5));所在的行.
    说明测试失败是由这个断言引起的,由于这个断言测试入参大于32时的函数返回值正确性,所以我们就知道程序没有考虑到返回值超过int类型范围的情况.返回到代码清单 错误!文档中没有指定样式的文字.前文分段函数代码中将第13~15行被注释的代码放出来,重新运行测试,你将发现测试全部通过了.
    这也说明,编写一个有效测试用例并非易事,程序路径100%覆盖,完美的测试用例往往很难达到.当然,你可以依照一些经验性的原则,其中最大的一条就是:关注关键点.测试用例编写的技巧,超过了本文的范围,读者可以自行参考相关的书籍.
    提示:
    有时,JBTestRunner右边的帧窗口虽然内容已经超出,但滚动条却没有显示出来,想来应该是JBuilder一个小小的Bug吧.你可以在帧窗口中右击,在弹出的菜单中去除Word Wrap设置项,或者手工移动一下左右两帧间的分隔栏,滚动条就会显示出来了.
    用套件捆绑运行多个测试用例
    目前我们只为Subsection类生成了一个测试用例,在这节里,我们按照前述的方法,通过Test Case向导为StringUtils类创建一个测试用例代码框架,并编写测试方法,然后将这两个测试用例捆绑组合在一个测试套件中一起运行.
    在这节里,我们按照前述的方法,通过Test Case向导为StringUtils类创建一个测试用例代码框架
    目前我们只为Subsection类生成了一个测试用例,在这节里,我们按照前述的方法,通过Test Case向导为StringUtils类创建一个测试用例代码框架,并编写测试方法,然后将这两个测试用例捆绑组合在一个测试套件中一起运行.
    选中StringUtils类,通过File->New..->Test,双击Test Case图标为StringUtils类的string2Array()方法创建测试用例,接受默认的测试用例类名TestStringUtils.
    在向导生成的测试用例代码框架中,删除测试固件(因为是静态方法,没有必要用固件),即删除StringUtils的成员变量声明,setUp()和tearDown()方法.并在类中定义一个isArrayEquals()的方法,删除向导生成的testString2Array()测试方法体中的内容,编写自己的测试代码,其最终代码如下所示:
    代码清单 错误!文档中没有指定样式的文字.TestStringUtils:StringUtils类的测试用例
    1. package chapter25;
    2. import junit.framework.*;
    3. public class TestStringUtils extends TestCase
    4. {
    5. public void testString2Array() {
    6. String str1 = null, str2 = "", str3 = "a", str4 = "a,b,c",str5 = ",a,b,";
    7. String[] arr1 = null, arr2 = {""}, arr3 = {"a"}, arr4 = {"a", "b", "c"},
    8. arr5 = {"", "a", "b", ""}, trimArr5 = {"a", "b"};
    9.
    10. assertNull(StringUtils.string2Array(str1, ',', false));
    11. assertTrue(isArrayEquals(arr1, StringUtils.string2Array(str1, ',', false)));
    12. assertTrue(isArrayEquals(arr2, StringUtils.string2Array(str2, ',', false)));
    13. assertTrue(isArrayEquals(arr3, StringUtils.string2Array(str3, ',', false)));
    14. assertTrue(isArrayEquals(arr4, StringUtils.string2Array(str4, ',', false)));
    15. assertTrue(isArrayEquals(arr5, StringUtils.string2Array(str5, ',', false)));
    16. assertTrue(isArrayEquals(trimArr5, StringUtils.string2Array(str5, ',', true)));
    17. assertFalse(isArrayEquals(StringUtils.string2Array(str5, ',', false),
    18. StringUtils.string2Array(str5, ',', true)));
    19. }
    20.
    21. //判断两个字符数组是否相等
    22. private boolean isArrayEquals(String[] arr1, String[] arr2) {
    23. if (arr1 == null || arr2 == null) {
    24. if (arr1 == null && arr2 == null) {
    25. return true;
    26. } else {
    27. return false;
    28. }
    29. } else if (arr1.length != arr2.length) {
    30. return false;
    31. } else {
    32. for (int i = 0; i Project Properties...->Run->在Run设置页中取消TestSubsection运行设置项的Context Menu选项,否则只会运行原TestSubsection的测试用例.
    只包括10个类左右的小型项目工程也许无需用到测试套件,仅通过逐一单独运行测试用例来完成测试就可以了,但对于一个包含较多测试用例的工程,测试套件能给你带来极大的方便,它将多个测试用例捆绑在一起运行,达到一呼而百应的批量处理效果.
    下面我们就来为TestSubsection和TestStringUtils这两个测试用例创建一个测试套件,并通过测试套件运行这两个测试.
    1.File->New...->Test->在Test页中双击Test Suite图标启动创建测试套件的向导,如下图所示:
    图 错误!文档中没有指定样式的文字.选择套件中捆绑的测试用例
    在对话框列表中已经列出了工程中已有的两上测试用例类,你可以通过右边的Add...和Remove添加或删除测试用例.你可以通过Add Recursively,将指定目录下的所有测试用例一并加入.
    点击Next到下一步.
    2.指定测试套件类名.
    图 错误!文档中没有指定样式的文字.指定测试套件类名
    接受JBuilder为测试套件所提供的默认类名,按Finish完成该测试套件的创建,其代码如下所示:
    代码清单 错误!文档中没有指定样式的文字.测试套件类
    1. package chapter25;
    2. import junit.framework.*;
    3. public class TestSuite1
    4. extends TestCase
    5. {
    6. public TestSuite1(String s) {
    7. super(s);
    8. }
    9.
    10. public static Test suite() {
    11. TestSuite suite = new TestSuite();
    12. suite.addTestSuite(chapter25.TestStringUtils.class);
    13. suite.addTestSuite(chapter25.TestSubsection.class);
    14. return suite;
    15. }
    16. }
    测试套件类最主要的代码是suite()方法(第10~15行),首先在方法中声明一个TestSuite变量,通过addTestSuite()方法将TestStringUtils和TestSubsection测试用例捆绑在一起,你也可以通过这个方法添加其他的测试用例类.
    TestSuite除可以将整个测试用例捆绑外,还可以捆绑另外的一个测试套件或一个测试用例中的测试方法:
    l 添加一个测试套件
    suite.addTest(suite_1)
    l 添加测试用例某个方法
    suite.addTest(new TestSubsection ("testGetValue"))
    在工程窗格资源树的TestSuite1文件节点上右击,在弹出的菜单中选择Run Test using Defaults,JBuilder启动JBTestRunner,运行套件中捆绑的所有测试用例,其窗口如下图所示:
    图 错误!文档中没有指定样式的文字.用测试套件运行组合运行多个测试用例
    TestSuite下有两个测试用例类,测试用例节点下是测试方法节点.
    创建测试固件
    在测试用例中通过setUp(),tearDown()创建测试固件,只能使这个测试固件在单个测试用例的不同测试方法中共用,如果有多个测试用例都需要使用相同的测试固件,就需要将测试固件抽取到一个独立的类中
    在测试用例中通过setUp(),tearDown()创建测试固件,只能使这个测试固件在单个测试用例的不同测试方法中共用
    在测试用例中通过setUp(),tearDown()创建测试固件,只能使这个测试固件在单个测试用例的不同测试方法中共用,如果有多个测试用例都需要使用相同的测试固件,就需要将测试固件抽取到一个独立的类中.JBuilder提供了3个预定义的测试固件类,它们分别是:
    ·JDBC测试固件(JDBC Fixture):用于获取数据库连接的测试固件,用户仅需要通过设置一些数据库信息,就可以用方便的方法获取数据连接.
    ·JNDI 测试固件(JNDI Fixture):用于模拟从JDNI环境中获取对象的测试固件.
    ·比较测试固件(Comparision Fixture):将测试输出到外部文件中,以便第二次测试时进行比较.
    ·自定义测试固件(Custom Fixture):用户自定义的测试固件.
    如果对JUnit的框架结构非常了解,也许这些JBuilder扩展的测试固件对你来说意义并不大,它们无非是构建一些常见的测试环境罢了,你完全可以自己编写.在本节里,我们介绍两个测试固件.
    JDBC测试固件
    如果你的工程中已经有一个获取数据连接的公共类,你也有必要构建一个JDBC测试固件,因为JDBC测试固件不但可以直接通过创建测试用例的向导直接指定,此外,JDBC测试固件还提供了许多面向测试的方法.
    为了创建JDBC测试固件,我们先创建一个JDataStore的数据库,其数据文件位于/db/hr.jds,这个数据库的用户名和密码是:sysdba/123456.hr.jds数据库中有一张EMPLOYEE的表,其结构如下所示:
    图 错误!文档中没有指定样式的文字.EMPLOYEE表的数据
    EMPLOYEE有3个字段,分别是ID,NAME和AGE,分别是String,String和int类型,并按上图所示填入3条记录.
    为了演示JDBC测试固件的具体使用,我们设计两个业务类:Employee和EmployeeDAO,尔后用JDBC测试固件为测试EmployeeDAO提供数据连接.这两个类的代码如下:
    代码清单 错误!文档中没有指定样式的文字.Employee.java类
    1. package chapter25.db;
    2. public class Employee
    3. {
    4. private String id;
    5. private String name;
    6. private int age;
    7. public Employee(String id, String name, int age) {
    8. this.id = id;
    9. this.name = name;
    10. this.age = age;
    11. }
    12. public String getId() {
    13. return id;
    14. }
    15. public String getName() {
    16. return name;
    17. }
    18. public int getAge() {
    19. return age;
    20. }
    21. public boolean equals(Object o) {
    22. if (o instanceof Employee) {
    23. Employee e1 = (Employee) o;
    24. return id.equals(e1.getId()) && name.equals(e1.getName()) &&age == e1.getAge();
    25. } else {
    26. return false;
    27. }
    28. }
    29. }
    Employee类用于描述EMPLOYEE表的一条记录,该类访问数据库的EmployeeDAO代码如下所示:
    代码清单 错误!文档中没有指定样式的文字.EmployeeDAO.java类
    1. package chapter25.db;
    2. import java.sql.*;
    3. public class EmployeeDAO
    4. {
    5. private Connection conn;
    6. public EmployeeDAO(Connection conn) {
    7. this.conn = conn;
    8. }
    9. public Employee findById(String id) throws SQLException
    10. {
    11. String sqlStr = "select * from employee where id ='"+id+"'";
    12. Statement stat = conn.createStatement();
    13. ResultSet rs = stat.executeQuery(sqlStr);
    14. if (rs.next()) {
    15. return new Employee(id,rs.getString("name"),rs.getInt("age"));
    16. }else{
    17. return null;
    18. }
    19. }
    20. }
    为了节省篇幅,我们仅提供一个访问数据库的访问方法:findById(),即通过id查找Employee对象.
    下面,我们利用JBuilder向导创建一个JDBC测试固件:
    1. File->New...->Test->在Test页中,双击JDBC Fixture图标,启动创建向导,其对话框如下所示:
    图 错误!文档中没有指定样式的文字.指定JDBC测试固件类名
    在Class name中为JDBC测试固件指定类名:HrJdbcFixture,接受其他的默认设置,按Next到下一步.
    2.设置连接数据库的信息.
    在这步里,JBuilder提供了大部分数据库驱动程序的选择和连接信息设置,其对话框如下所示:
    图 错误!文档中没有指定样式的文字.指定数据库连接信息
    ·Driver:选择borland.databstore.jdbc.DataStoreDriver类.JDBC测试固件提供了对大多数数据库的支持.其中下拉框中暂不可用的数据库驱动器类显示为红色,你可以通过配置工程扩展类库使它们可用.
    ·URL:点击其后的…按钮,弹出Create URL for DataStore对话框,如下图所示:
    图 错误!文档中没有指定样式的文字.构造DataStore数据连接URL的对话框
    该对话框的设置内容会随着数据库类型的不同而变化.对于JDataStore数据库,该对话框提供了两个选项,如果数据库文件放在本机上时用第一个设置项,否则用第二个设置项.我们选择第一种选项,点击其后的…按钮,导航到/db/hr.jds并选择之,按OK返回向导主对话框窗口.
    ·User name:sysdba.
    ·Password:123456.
    按对话框下的Test Connection测试连接,应该会返回一个Success信息报告连接测试成功.按Finish创建JDBC 测试固件,其代码如下所示:
    代码清单 错误!文档中没有指定样式的文字.HrJdbcFixture.java
    1. package fixture;
    2. import java.sql.*;
    3. import java.io.*;
    4. import com.borland.jbuilder.unittest.JdbcFixture;
    5. public class HrJdbcFixture
    6. extends JdbcFixture
    7. {
    8. public HrJdbcFixture(Object obj) {
    9. super();
    10. super.setUrl("jdbc:borland:dslocal:D:/JTJB2005/chapter25/db/hr.jds");
    11. super.setDriver("com.borland.datastore.jdbc.DataStoreDriver");
    12. super.setUsername("sysdba");
    13. super.setPassword("123456");
    14. }
    15.
    16. public void setUp() {
    17. super.setUp();
    18. }
    19.
    20. public void tearDown() {
    21. super.tearDown();
    22. }
    23. }
    JDBC测试固件承继了com.borland.jbuilder.unittest.JdbcFixture,这个类的重要方法包括:
    ·dumpResultSet():将一个ResultSet导到一个Writer中,该方法接受两个参数,一个是ResultSet另一个是Writer.
    ·getConnection():获取一个数据连接.
    ·runSqlBuffer():执行缓存于StringBuffer对象中的SQL语句.
    ·runSqlFile():执行保存在文件中的SQL语句,通过入参指定SQL文件的地址.
    ·setDriver():设置JDBC驱动器.
    ·setUrl():设置数据连接的URL.
    ·setUsername():设置用户名.
    ·setPassword():设置密码.
    提示:
    通过向导创建JDataStore的JDBC测试固件,虽然可以直接在对话框中选择com.borland.datastore.jdbc.DataStoreDriver驱动器,但运行这个JDBC测试固件时,JBuilder却报这样的错误信息:java.lang.ClassNotFoundException: com.borland.datastore.jdbc.DataStoreDriver.原来是JBuilder通过向导创建JDBC测试固件时,并没有直接将驱动器类加载到工程类库中,所以你需要手工通过Project->Project Properties...->Paths中,将JBuilder类库中名为JDataStore类库项加到工程类库中.
    由于EMPLOYEE表的数据可能会随着测试的进行不断更改,这样在测试时测试规则就很难制定,因为规则的制定必须基于一个假设的环境.举个例子,我们现在要测试findById()方法,就必须知道EMPLOYEE表中有哪些数据,所以在测试开始时就必须创建好一些特定的数据.由于JDBC固件可以执行保存在外部文件中的SQL,所以我们创建一个insert.sql文件,将其放置在/db/insert.sql下,文件的内容如下:
    delete from employee;insert into employee values('0004','大山',23);insert into employee values('0005','英华',30);insert into employee values('0006','柯明',31);
    运行这个SQL语句时,先清空EMPLOYEE表中的数据,然后再插入3条特定的记录.下面,我们来创建应用JDBC测试固件的TestEmployeeDAO测试用例类.
    1.在编辑器中激活EmployeeDAO.
    2.File->New...->Test->双击Test Case图标启动创建测试用例的向导,在向导第1,2步为EmployeeDAO的创建一个名为TestEmployeeDAO的测试用例,这个测试用例对EmployeeDAO的findById()方法进行功能测试.
    3.在向导的第3步选择测试固件,在向导对话框中我们前面创建的HrJdbcFixture已经出现在列表中.你也可以通过对话框的Add...和Remove选择不同的测试固件.
    图 错误!文档中没有指定样式的文字.选择测试固件
    按Finish直接创建TestEmployeeDAO的测试用例,其代码如下所示:
    代码清单 错误!文档中没有指定样式的文字.TestEmployeeDAO.java,向导创建的测试用例类
    1. package chapter25.db;
    2. import junit.framework.*;
    3. import fixture.*;
    4. import java.sql.*;
    5. public class TestEmployeeDAO extends TestCase {
    6. private EmployeeDAO employeeDAO = null;
    7. HrJdbcFixture hrJdbcFixture;
    8. protected void setUp() throws Exception {
    9. super.setUp();
    10. /**@todo verify the constructors*/
    11. employeeDAO = new EmployeeDAO(null);
    12. hrJdbcFixture = new HrJdbcFixture(this);
    13. hrJdbcFixture.setUp();
    14. }
    15.
    16. protected void tearDown() throws Exception {
    17. employeeDAO = null;
    18. hrJdbcFixture.tearDown();
    19. hrJdbcFixture = null;
    20. super.tearDown();
    21. }
    22.
    23. public void testFindById() throws SQLException {
    24. String id = "";
    25. Employee expectedReturn = null;
    26. Employee actualReturn = employeeDAO.findById(id);
    27. assertEquals("return value", expectedReturn, actualReturn);
    28. /**@todo fill in the test code*/
    29. }
    30. }
    测试用例在setUp()方法中实例化HrJdbcFixture对象,并调用其setUp()方法初始化环境.只有JDBC测试固件的setUp()方法执行后(第13),才可调用JDBC测试固件的其他方法,如getConnection()等,所以JDBC测试固件的setUp()是其初始化方法.下面我们对这个TestEmployeeDAO进行改造,改造的代码如下粗体代码所示:
    代码清单 错误!文档中没有指定样式的文字.改造后的TestEmployeeDAO类
    1. …
    2. public class TestEmployeeDAO extends TestCase {
    3. …
    4. protected void setUp() throws Exception {
    5. super.setUp();
    6. hrJdbcFixture = new HrJdbcFixture(this);
    7. hrJdbcFixture.setUp();
    8. employeeDAO = new EmployeeDAO(hrJdbcFixture.getConnection());
    9. hrJdbcFixture.runSqlFile("D:/JTJB2005/chapter25/db/insert.sql",true);
    10. }
    11. …
    12. public void testFindById() throws SQLException {
    13. Employee expectEmp = new Employee("0004","大山",23);
    14. Employee realEmp = employeeDAO.findById("0004");
    15. assertNotNull(realEmp);
    16. assertEquals(expectEmp,realEmp);
    17. }
    18. }
    因为JDBC测试固件需要在setUp()方法调用后,其他方法才可用,所以在TestEmployeeDAO的setUp()方法中,我们将EmployeeDAO的实例化方法移到后面,以便实例化EmployeeDAO时可以通过hrJdbcFixture.getConnection()获取数据连接(第8行).在第9行,执行insert.sql文件,清除表中原来的数据并插入3行测试数据.
    在第13~14行,通过EmployeeDAO的findById()方法查找返回ID为0004的Employee对象,在第15~16行设定两个测试规则.
    运行这个带JDBC测试固件的测试用例,HrJbdcFixture测试固件先准备好测试环境,然后再执行TestEmployeeDAO的testFindById()测试方法.
    比较测试固件
    比较固件用于记录下当前的测试记录,以便和下一次的输出比较.比较固件类继承于com.borland.jbuilder.unittest.TestRecorder,而TestRecorder类继承java.io.Writer.所以如果在测试时,需要用Writer输出信息就可以考虑使用比较固件了,它提供了许多易用的输出信息的方法.你可以通过向导来创建比较固件.
    TestRecorder共有 4个记录模式的常量,它们分别是:
    ·UPDATE:比较固件将当前输出信息和已存在的信息文件相比较,如果文件没有存在则新创建一个文件,记录输出信息.
    ·COMPARE:比较固件将当前输出的信息和已经存在的信息比较.
    ·RECORD:比较固件记录当前输出的信息,如果原来已经有输出文件存在,覆盖之.
    ·OFF:关闭比较固件的功能.
    注意:
    在创建记录文件后,假设你更改了测试用例或测试套件,需要重新初始化这个输出文件:将TestRecorder的输出模式设置为RECORD,创建文件后再将其调整为UPDATE.输出的数据文件是二进制文件,放在和源程序文件相同的目录下且和测试用例类同名.
    下面是测试固件常用的方法,介绍如下:
    ·boolean print(String s)
    用TestRecorder打印一个字符串,如果模式为RECORD,且这个字符串和原来记录的不一致,则返回false.你可以设定这样的测试规则:
    assertTrue(recorder.print(result.toString())
    ·boolean println(String s)
    和print()相似,只不过添加一个换行.
    ·boolean compareObject(Object o)
    调用传入对象的equals()方法和用前面用recordObject()记录的对象进行比较.
    ·boolean recordObject()
    记录一个对象,以便后面调用compareObject()方法进行比较.
    下面,我们创建一个比较固件,并应用这个比较固件为Employee类创建一个测试用例.
    1.File->New...->Test->在Test页中,双击Comparision Fixture图标启动创建比较固件类的向导,其对话框如下所示:
    图 错误!文档中没有指定样式的文字.指定比较固件名及属性
    ·Class name:测试固件类名,接受默认的ComparisionFixture1.
    ·Echo output to console:测试固件将信息同时输出到测试运行器的控制台上.
    ·Verbose output:测试固件将输出详细的信息.
    此外,Save comparision data in this directory指定比较输出信息文件的存放位置,可以通过其后的…按钮更改,这里我们接受默认的设置.按OK直接创建比较固件类,你代码如下所示:
    代码清单 错误!文档中没有指定样式的文字. 15 ComparisonFixture1.java,向导创建的测试固件类
    1. package fixture;
    2. import com.borland.jbuilder.unittest.TestRecorder;
    3. public class ComparisonFixture1 extends TestRecorder
    4. {
    5.
    6. public ComparisonFixture1(Object obj) {
    7. super();
    8. super.setMode(UPDATE);
    9. super.setVerbose(true);
    10. super.setEcho(true);
    11. String fileName = super.constructFilename("D:/JTJB2005/chapter25/test",obj);
    12. super.setOutputFile(fileName);
    13. }
    14.
    15. public void setUp() {
    16. }
    17.
    18. public void tearDown() {
    19. }
    20. }
    第8行将模式设置为UPDATE,而第9,10行对输出属性作设置.第11~12行指定输出文件的目录.
    2.创建TestEmployee测试用例类.
    File->New...->Test->在Test页,双击Test Case图标启动创建测试用例向导,为Employee类和构造函数创建TestEmployee测试用例类.在向导的第1步,你将看到如下的对话框:
    图 错误!文档中没有指定样式的文字.选择测试Employee类的构造函数
    点击Next一直到向导的第3步:

    列表中列出了工程的所有的测试固件,选择HrJdbcFixture,点击Remove删除这个固件,只留下ComparisionFixture1的固件,点击Finish直接创建TestEmployee测试用例类的代码框架,在代码框架基础上利用比较固件对Employee进行测试,其最终代码如下所示:
    代码清单 错误!文档中没有指定样式的文字.应用比较固件的测试用例
    1. package chapter25.db;
    2.
    3. import junit.framework.*;
    4. import fixture.*;
    5.
    6. public class TestEmployee extends TestCase {
    7. private Employee employee = null;
    8. ComparisonFixture1 comparisonFixture1;
    9.
    10. protected void setUp() throws Exception {
    11. super.setUp();
    12. employee = new Employee("0004", "王五", 23);
    13. comparisonFixture1 = new ComparisonFixture1(this);
    14. comparisonFixture1.setUp();
    15. }
    16.
    17. protected void tearDown() throws Exception {
    18. employee = null;
    19. comparisonFixture1.tearDown();
    20. comparisonFixture1 = null;
    21. super.tearDown();
    22. }
    23.
    24. public void testEmployee() {
    25. String id = "0004";
    26. String name = "王五";
    27. int age = 23;
    28. comparisonFixture1.print(employee.getId());
    29. comparisonFixture1.recordObject(employee);
    30. employee = new Employee(id, name, age);
    31. assertTrue(comparisonFixture1.print(employee.getId()));
    32. assertTrue(comparisonFixture1.compareObject(employee));
    33. }
    34. }
    在第12行实例化一个Employee对象,在第28行保持并打印出原employee对象的id值,在第31行进行比较;第29行记录原employee对象,在第31行进行两对象的比较.
    运行TestEmployee类,在测试运行器的测试输出标签页中,你将可以看到输出的信息,在测试用例所在的文件夹下将创建一个无后缀名的输出文件Employee.
    测试运行配置
    在一般情况下,你不必为每个测试用例类单独创建一个运行配置项,JBuilder会采用默认的运行配置运行测试用例.
    在测试用例向导的最后一步,允许你创建一个测试用例的运行配置项
    在测试用例向导的最后一步,允许你创建一个测试用例的运行配置项,如下图所示:
    图 错误!文档中没有指定样式的文字.创建运行测试项
    在一般情况下,你不必为每个测试用例类单独创建一个运行配置项,JBuilder会采用默认的运行配置运行测试用例.
    测试运行配置项在需要指定不同的测试运行器(默认为JBTestRunner),一次运行多个测试用例时,允许你进行特殊的定制.通过Project->Project Properties...->Run,在Run设置页中列出了工程所有已定义的运行配置项,Runtime Configurations列表中Type类型为Test的运行配置项即为测试运行配置项,可以通过对话框右边的Edit...按钮编辑这些运行配置项,如下图所示:
    图 错误!文档中没有指定样式的文字.运行配置页列表
    下面,我们来创建一个新的名为TestAllDbTest的运行配置项,用JUnit提供的junit.swingui.TestRunner测试运行器运行测试用例,使chapter25.db包下所有以Test打头的测试用例类一并运行.
    在图 错误!文档中没有指定样式的文字.点击New...按钮,弹出New Runtime Configuration的对话框,如下图所示
    图 错误!文档中没有指定样式的文字.TestSubsection运行
    在Name中填入TestAllDb.在Type中选择Test,对话框下部的窗口调整为测试运行配置的界面.默认Class单选框选中,允许你指定一个测试用例类,由于我们希望通过该配置项运行chapter25.db包下所有的测试用例,所以我们选择Package单选框,并通过其后的…按钮选择chapter25.db包.
    在Name starts with中填入Test,即运行所有类名以Test为前缀的类,此外,你还可以在Name ends with中指定类名后缀.
    注意:
    注意,如果包中有以Test打头的非测试用例类,运行这个测试运行配置项时,将会抛出错误,特别需要指出的是以Test为前缀的测试套件也是不允许的,满足过滤条件的类都必须是测试用例类.
    在Test Runner中包含3个测试运行器,分别是JBuilder Test Runner,JUnit SwingUI Test Runner
    和JUnit TestUI Test Runner.默认为JBuilder Test Runner,也即JBTestRunner,当然这个运行器功能最强大.对于好奇心强的开发人员来说,可能希望看看JUnit自带运行器的芳容,笔者也是其中的一位,所以这里,我们选择JUnit SwingUI Test Runner.
    对于New Runtime Configuration对话框其它的设置项,可以通过Help按钮获取JBuilder的帮助.
    在完成TestAddDb运行配置项的设置后,点击工具栏中 图标右边的向下箭头,在弹出的菜单中选择TestAddDb,如下图所示:
    图 错误!文档中没有指定样式的文字.通过测试运行配置项运行测试用例
    点击TESTALLDB项,JBuilder使用JUnit的junit.swingui.TestRunner运行chapter25.db包中的TestEmployeeDAO和TestEmployee两测试用例类,因为这两个用例类都以Test打头,运行器窗口如下所示:
    图 错误!文档中没有指定样式的文字.junit.swingui.TestRunner测试运行器
    在Test Hierarchy标签页中,列出了TestEmployeeDAO和TestEmployee两测试用例类,所以通过测试运行配置项,也可以实现测试套件相似的效果,当然还是没有办法达到测试套件的灵活度.假设测试用例命名没有规律,或者存在过滤冲突,这时就只得求助于测试套件了.
    总结
    JUnit的框架非常简单,只需要知道TestCase类的执行顺序,测试方法的命名规范就大体掌握了JUnit的测试框架,所谓测试固件和测试套件也是利用TestCase的这两个特征而提供的扩展技术.所以编写测试用例难的不在于框架的理解,在于测试规则的设置,而后者需要通过不断的实践总结才可以提升.
  • 下载地址 (推荐使用迅雷下载地址,速度快,支持断点续传)
  • 免费下载 DOC格式下载
  • 您可能感兴趣的
  • sqlserver2005jdbc  jdbc连接sql2005  sql2005jdbc  sql2005jdbc.jar  sql2005jdbc驱动  jdbcsql2005下载  jdbcformysql  javajdbc  mysqljdbc  sqljdbc4.jar