单元测试作业指导书(四)

类别:软件工程 点击:0 评论:0 推荐:
这一部分是Junit工具的简单使用说明,作为作业指导书的附件。

 

本文简单地介绍了如何使用Junit编写和组织自己的单元测试代码。

 

l         简单的测试用例

如何写测试代码呢?最简单的方式当然是在调试器中写成表达式的形式。你不必重新编译程序就可以改变调试表达式,并且你可以等看到了具体运行的对象再决定写什么样的调试表达式。另一种方式就是编写调试表达式输出一些东西到标准的输出流。这两种调试方式都有限制,因为它们需要你自己去分析产生的结果。同时,它们在组织方面也不是很好。比如,在第一种情况下一次仅仅可以执行一个调试表达式;在第二种情况下如果一个程序很多的输出语句,那将是一件可怕的事情。

Junit不需要你自己去判断正误,并且一次可以执行多个测试。要用Junit进行测试,你要做下面的事情:

1.       创建一个TestCase类型的实例。

2.       重载该类中的runTest()方法。

3.       如果要检查一个值是否正确,调用assert()方法并传送一个boolean类型的参值,如果该参数是true,则说明测试是成功的。

 

举例说明,要测试两个有相同currency属性的Money类型的对象相加。

    Public void testSimpleAdd() {

    Money m12CHF = new Money(12, “CHF”);

    Money m14CHF = new Money(14, “CHF”);

    Money expected = new Money(26, “CHF”);

    Money result = m12CHF.add(m14CHF);

    Assert(expected.equals(result));

}

 

如果你想做的测试和原来做过的很相近,就使用Fixture。如果你想执行多个测试,就创建一个Suite。

l         Fixture

如果你有多个测试作用在相同或相近的对象集合上,该怎么做呢?

执行测试需要依赖已知的一些对象。这些对象的集合就称为Fixture。当你做测试时,你可能常常会发现花费了很多的时间去构建fixture,而不是真正的测试数据。

通常地,同一fixture可以被用来做几个不同的测试。每一个测试用例传送不同的信息或者参数到fixture中从而得到不同的测试结果。

下面说明了如何建立通用的fixture:

1.       创建一个TestCase的子类。

2.       给fixture的每一部分添加一个变量实例。

3.       重载setUp()方法来初始化变量。

4.       重载tearDown()方法来释放在setUp()方法中分配的参数资源。

 

举例说明:如果几个不同的测试用例都要用到12Swiss Frances,14Swiss Frances和28US Dollars,那么首先创建一个fixture。

    Public class MoneyTest extends TestCase {

    Private Money f12CHF;

    Private Money f14CHF;

    Private Money f28USD;

        Protected void setUp() {

    F12CHF = new Money(12, “CHF”);

    F14CHF = new Money(14, “CHF”);

    F28USD = new Money(28, “USD”);

}

}

 

一旦建立了Fixture,接下来就可以随便写多少测试了。

l         Test Case

当fixture创建后,如何编写并且调用一个单独的测试用例呢?

 

如果没有fixture,写一个测试用例很简单——在TestCase的匿名子类中重载runTest方法就可以了。

Junit提供了一个很简便的方式写关于一个fixture的测试。下面就是你要做的:

1.       在fixture类中写测试用例的方法。注意要保证它是public类型的,否则它不能被映射(reflection)所调用。

2.       创建一个TestCase的实例,并且传送测试用例方法的名字给构造函数。

 

举例说明,要测试一个Money类型的实例和一个MoneyBag类型的实例相加。

public void testMoneyMoneyBag() {

    Money bag[] = {f26CHF, f28USD};

    MoneyBag expected = new MoneyBag(bag);

    AssertEquals(expected, f12CHF.add(f28USD.add(f14CHF)));

}

创建一个MoneyTest的实例,这个实例将运行此测试用例:

new MoneyTest(“testMoneyMoneyBag”);

当测试执行的时候,测试的名字被用来查找要执行的方法。

 

如果你有几个测试,就组织它们成为一个Suite。

l         Suite

如果一起执行多个测试呢?

如果你有两个测试,你当然想同时执行它们。Junit提供了一个对象——TestSuite,这个对象可以将任意数量的测试用例放在一个执行。

比如,要运行一个单独的测试用例,你可以运行:

TestResult result = (new MoneyTest(“testMoneyMoneyBag”)).run();

 

要创建有两个用例的suite并运行它们就可以:

TestSuite suite = new TestSuite();

Suite.addTest(new MoneyTest(“testMoneyEquals”));

Suite.addTest(new MoneyTest(“testSimpleAdd”));

TestResult result = suite.run();

 

另一个方式是让Junit来从一个TestCase中执行一个suite。要这样做,你将你的TestCase的类作为参数传送给TestSuite的构造函数。

TestSuite suite = new TestSuite(MoneyTest.class);

TestResult result = suite.run();

 

如果你只是要执行包含了测试用例的子集时就使用手工的方式。否则最好使用自动suite抽取的方式。这样避免了你在增加一个新的测试用例的时候更新suite的创建代码。

TestSuite不仅可以包含TestCase,实际上,只要实现了Test接口的对象都可以加入其中。比如,可以在你的代码中创建一个TestSuite,我在我代码中也创建一个,我们可以通过创建一个TestSuite来包含它们,从而一起执行。

TestSuite suite = new TestSuite();

Suite.addTest(Kent.suite());

Suite.addTest(Erich.suite());

TestResult result = suite.run();

l         TestRunner

如何运行测试并收集结果?

一旦建立了TestSuite,就可以运行它了。Junit提供了运行suite并显示结果的工具。你要让你的suite对TestRunner来说是可以访问的,设置一个静态的方法suite(),这个方法要返回一个TestSuite。

比如,使一个MoneyTest suite对TestRunner来说是可以访问的,然后在你的MoneyTest中加入下面的代码:

public static Test suite() {

    TestSuite suite = new TestSuite();

    Suite.addTest(new MoneyTest(“testMoneyEquals”));

    Suite.addTest(new MoneyTest(“testSimpleAdd”));

    Return suite;

        }

如果一个TestCase类没有定义一个suite()方法,那么TestRunner将提取出一个suite出来,并在suite加入所有的”test”开头的方法。

Junit提供了两个图形和一个文本格式的TestRunner工具。运行图形工具可以键入java junit.swtui.TestRunner或者junit.swingui.TestRunner。图形用户界面提供了一个窗口,包括:

l         键入suite方法所在的类的名字。

l         一个运行按钮,可以执行测试。

l         一个表示运行状态的进度条。

l         失败测试的列表。

 

如果测试没有成功,则失败的测试结果将在底部的列表中显示出来。Junit将failutue和error分开来说。Failure是可以预料的并且用assertion来检查的。Error是不可预料的就像ArrayIndexOutOfBounds等。下图显示了一个失败测试的例子:

要找出更多的failure或者error,可以点击”Show”按钮。下图显示了一个failure的运行堆栈。

       

 

Junit还提供了一个分批处理的接口。键入java junit.textui.TestRunner,接着加上包括了suite()方法的类的名字。这个接口将结果以文本的方式输出出来。当然你可以定义一个main()方法,然后调用batch接口。

比如:对MoneyTest来说运行batch TestRunner,可以:

public static void main(String args[]) {

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

}

有了main()方法,你可以运行测试,仅仅在系统提示符后键入java MoneyTest就可以了。

要使用图形RunnerTest或者文本的TestRunner,你要注意junit.jar要放到你系统的CLASSPATH中。

本文地址:http://com.8s8s.com/it/it37557.htm