Junit:单元测试和编码的协作

发表于:2007-9-19 17:18

字体: | 上一篇 | 下一篇 | 我要投稿

 作者:翻译:ALEX    来源:网络转载

#
Junit
分享:

        自1947年9月9日一只飞蛾被发现困在Harvard Mark Ⅱ中开始,调试问题就一直困扰着程序员。(这第一个“真实的Bug”,至今还存放在Smithsonian的美国国家历史博物馆)。计算机先驱Manrice Wilkes在谈到他意识到调试的严重性的时候说道:“我生命中余下的时间,将有很大的一部分将被用于从我自己所写的代码中查找错误。”他的这个解释在很多的计算机专家身上得到了验证。

        单元测试是一个检测bug的方法。首先,单元测试适用于单独的代码片断。例如函数,方法。除非这些最小的代码片断是正确的,否则,整个软件的“大厦“将会倒塌。其次,单元测试让代码的编写者也同时来参与代码的测试。通过测试能够查出bug,但程序员除了编码不愿花费时间在其他任何事上。

        JUnit是一个开放源代码的Java类库,目的是让单元测试更简单、有趣。事实上JUnit是如此的有趣以至于程序员会爱上编写测试代码。Kent Beck和Erich Gamma从Beck的SmallTalk测试框架中获得了灵感并建立了JUnit项目。最初的想法是让编码和测试能同时进行。程序员写若干行的代码,然后为这几行的代码编写测试。如果没有通过测试,就改正程序中的bug;如果正常通过测试,就继续编码和测试。所有的测试码随着代码的变化而变化,一旦运行代码发生变化,通过回归测试的方法能保证整个软件不会因为这些变化而遭到破坏。 

        编码和测试的整合是极限编程XP(eXtreme Programming)和敏捷软件开发活动的中心环节。在敏捷软件开发过程中,软件通过不断增加实现功能来构建,简言之就是活动的突发催生软件功能的完善。)为了达到这个目的则必须保证所有已经完成的代码都是正确的,只有这样才能有自信在这些代码的基础上进行后续开发。

一、JUnit简介

        在单元测试中,我们经常编写这样的代码:按实际需求提供输入的代码和以输出结果形式展示的代码的运行情况。程序员长期使用的一个简单的方法是:编写一系列的if条件语句与预期的结果来进行比较。在JUnit中,我们并不需要这些if语句,而是写断言(assertion)。断言是这样一个方法:预先标志出期望的结果,并将得到的结果与之进行比较,如果匹配,则断言成功,否则断言失败。

        一般的说,测试需要建立“测试框架”:例如初始化变量,创建对象等。在JUnit中,准备工作被称为装配(setup)。setup和assertions是相互独立的,所以相同的测试框架可适用于若干独立的测试。setup过程在测试以前执行。

        而当一个测试结束的时候,可能需要对测试框架进行一些清理活动。在JUnit中,清理活动被称为拆卸(TearDown)。它保证每一个测试不会留下任何的影响。如果接下来有另一个测试活动开始了,那么这个测试的setup过程就能被正确得执行。setup和teardown被成为一个测试的固定环节

        单独的测试被称为测试用例(Test Cases),测试用例几乎不存在于真空中。如果一个项目经历了若干个单元测试,就能积累一定数量的测试用例集。程序员往往将这些测试一起运行。如果测试一起运行,就将测试联合成为测试组(test suites)。这种情况下,程序员将多个测试用例组合成为一个测试组(test suites),作为一个单独的整体来运行。

二、一个例子

        用实践来理解JUnit往往更简单。设想我们需要一个Complex类(当然不是从其他地方得到现成的)。这个Complex类应当包含常规的复数运算和操作,我们会对这些方法进行测试。

        首先,新建一个TestCase子类。在这个子类中,为fixture的每一部分(setup和teardown)新建实例变量。然后重写setUp()(注意保留)方法以初始化变量,重写tearDown()方法以清理所有测试过程中使用的资源从而避免任何的副作用。在这个例子中,所有的操作并没有副作用,所以我们并不需要重写tearDown()方法。Figure 1(a)中展示了如何创建一个TestCase子类并重写setUp()方法。


(a)

       import junit.framework.TestCase;

       import junit.framework.Test;

       import junit.framework.TestSuite;

       public class ComplexTest extends TestCase {

              private Complex a;

              private Complex b;

              protected void setUp() {

                     a = new Complex(1, -1);

                     b = new Complex(2, 5);

              }

       }

       (b)

       public void testComplexEquality()

              Complex expected = new Complex(1, -1);

              assertEquals(expected, a);

       }

       public void testComplexAddition() {

              Complex expected = new Complex(3, 4);

              assertEquals(expected, a.add(b));

       }

       public void testComplexMultiplication() {

              Complex expected = new Complex(1*2 - (-1)*5,1*5 + (-1)*2);

              assertEquals(expected, a.multiply(b));

       }

(c)

       public static Testsuite() {

              return new TestSuite(ComplexTest.class);

      }

        Figure 1 一个复数类例子:(a)JUnit测试的setup,(b)JUnit测试的实例,(c)在一个类中为所有实例动态得创建一个测试组(test suite)

21/212>
《2023软件测试行业现状调查报告》独家发布~

关注51Testing

联系我们

快捷面板 站点地图 联系我们 广告服务 关于我们 站长统计 发展历程

法律顾问:上海兰迪律师事务所 项棋律师
版权所有 上海博为峰软件技术股份有限公司 Copyright©51testing.com 2003-2024
投诉及意见反馈:webmaster@51testing.com; 业务联系:service@51testing.com 021-64471599-8017

沪ICP备05003035号

沪公网安备 31010102002173号