[转载]在Eclipse中使用 JUnit(Using JUnit With Eclipse IDE)

This article is going to introduce you to JUnit, a tool for project testing and debugging. After introducing the theory of test-driven development, we'll move on to a step-by-step explanation of how you can create your JUnit tests with the help of the popular Eclipse IDE. 这篇文章将向你介绍 Junit,一个用来在项目中进行测试和调试的工具。在介绍完 TDD(以测试驱动开发)理论后,将进一步讲解怎样在流行的 Eclipse中建立你自己的 JUnit测试。向你展示如何测试 Hello World这样简单的程序......              在 Eclipse 中使用 JUnit(翻译)
    这篇文章将向你介绍 Junit,一个用来在项目中进行测试和调试的工具。在介绍完 TDD(以测试驱动开发)理论后,将进一步讲解怎样在流行的 Eclipse中建立你自己的 JUnit测试。向你展示如何测试 Hello World这样简单的程序。
   
    许多书上都讨论了自动测试,但是只有很少的著作注意到这么一个问题,那就是怎样把这些测试组织起来。随着测试的增加,放置和调用这些测试却变得更加麻烦。这将成为一个重要问题,以至于出现了 TDD,极限编程( XP)使 TDD得以普及。另外,你可以这样理解 TDD:通过测试来开发。
   
    TDD 的主要规范:
   
    在编写程序代码之前,与之对应的自动测试必须被写好。甚至程序代码并不存在,那也要看见一个失败的测试结果。
    在测试通过后,副本代码必须被丢弃。
   
    有一个具体步骤(可能指的是《 Extreme Programming》)可以被任何一个程序员来参考,而不需要特殊的其他方法。在我们开始写测试之前,这些步骤(章节)应该被首先阅读——怎样组织自动测试。
   
    讲解一下不同种类的测试:
   
    单元测试:检测模块(也就是类)的正确性。如果对象需要访问外部的数据资源,例如数据库,就需要模拟一个 mock objects,但在实际中真实数据与测试环境是不同的。
    客户测试:这是功能性、系统、和验收测试。用来测试整体的系统特性。在 XP中,这些测试由用户编写。
    综合测试:介于用户测试和单元测试之间的桥梁。综合测试帮助测试应用程序的交互性。一般情况下, mock objects不被用于综合测试,它会增加测试时间。同样,综合测试经常依赖特殊的测试环境,例如数据库送来的测试数据。综合测试也需要用到外部类库。例如为 J2EE应用程序进行综合测试的类库 Cactus。解释这些测试超出了本文的范围,需要更加详细的信息请参考 http://jakarta.apache.org/cactus/
    开发人员测试:这是用来让开发人员检验自己代码或新函数的。对于每一个开发人员,只要有可能,就需要有更多的测试来检验代码。组织这些测试和组织程序代码一样重要。
   
    在以下章节,只要提到“测试”,那就指的是开发人员测试。
    
    我们几乎准备好开始建立测试了,先应该为我们的测试选择名字。你也许会说,“这不是问题:把‘ Test’这个字放在类名前面,就好了!”不会这么快!让我来说一下这个步骤存在的问题:
   
    在 TDD中,被测试的类或者方法还不存在。
    一个测试能够覆盖多个方法,甚至多个类,这是可能的。
   
    以上只是一些普遍问题;还存在更多的问题。
   
    让我来提一个建议,在测试命名时:测试类的名字应该让人一眼就知道这是一个测试类,且能说明它要测试什么,注意是否和其他类重名。按照以上建议做,就很简单了,也不用担心名字太长或难听。
   
    即将在 Eclipse中用 JUnit工具创建我们第一个测试了。假设你已经下载了一个最新的 Eclipse版本。如果还没有,你应该去官方站点 http://www.eclipse.org下载。还需要 JUnit,也可以从 http://www.junit.org/下载。
   
    运行 Eclipse。新建一个 workplace项目,点击 文件 -> 新建 -> 项目,选择 Java项目,点击 下一步。起一个项目名称,例如 ProjectWithJUnit。点击 完成。这样就完成新项目的建立了。再来配置一下 Eclipse,在构建路径中添加 JUnit类库。在工具条上点击 项目 -> 属性,选择 Java构建路径,选择 添加外部JAR,浏览 Junit被存储的目录,选择 junit.jar,点击 打开。你将会看见 JUnit出现在库的列表中。点击 确定,让 Eclipse重建路径。
   
    现在开发我们的“ Hello World”例子。按照 TDD的规则,应该在代码建立以前先把测试写好。为了能够在某出开始,我们假设未来的类名是 HelloWorld,并且有一个方法 Say(),这个方法返回 String的值(例如“ Hello World!”)。
   
    建立测试,在 ProjectWithJUnit的标题上面点击右键,选择 新建 -> 其他,展开“ Java”选项,选择 JUnit。在右边的栏目对话框中选择测试案例,然后下一步。参考图 1。
 
               Image
                    图 1. 在 Eclipse中建立 JUnit测试
   
    在测试类这一栏中,写上将要被测试的类名 HelloWorld。选择一个 测试案例的名字,例如 TestThatWeGetHelloWorldPrompt(是的,看上去很长,但是很清楚它的行为。)点击 完成
   
    TestThatWeGetHelloWorldPrompt的代码如下:
    import junit.framework.TestCase;
    public class TestThatWeGetHelloWorldPrompt
    extends TestCase {
        public TestThatWeGetHelloWorldPrompt(
            String name) {
            super(name);
        }
        public void testSay() {
            HelloWorld hi = new HelloWorld();
            assertEquals("Hello World!", hi.say());
        }
        public static void main(String[] args) {
            junit.textui.TestRunner.run(
                TestThatWeGetHelloWorldPrompt.class);
        }
    }
    代码并不复杂;只是有点与众不同。然而,让我们考察一下细节。我们继承了 JUnit的 TestCase类,它在 JUnit的 javadocs定义为“运行众多测试的夹具。” JUnit也有 TestSuite类,它是一组测试案例的集合,但在本文中不做讨论。
    建立测试案例的步骤如下:
    1、建立一个 junit.framework.TestCase的实例。
    2、定义一些以“ test”开头的无返回方法(例如 testWasTransactionSuccessful(), testShow(),等等)。
    TestThatWeGetHelloWorldPrompt.java包含这些: TestCase的子类和一个叫做 testSay()的方法。这个方法调用了 assertEquals()函数,它用来比较我们预期的值和由 say()返回的值。
   
    main()方法用来运行测试和显示输出的。 JUnit的 TestRunner处理测试,提供基于图像和文本的输出表现形式。我们使用基于文本的版本,因为 Eclipse支持它,且也适合我们。当开始运行后,基于文本的版本测试会以文本形式输出, Eclipse会把这些输出自动变成图像界面的输出。
   
    按照 TDD规范,首次运行测试,应该故意让它失败。点击 运行 -> 运行为 ->Junit 测试(记住 TestThatWeGetHelloWorldPrompt.java应该被突出的显示在包资源管理器中)。在左边窗口,应该看见 JUnit窗口而不是 包资源管理器,它显示一个红条,一次失败的测试,具体的失败原因参看图 2。如果没有自动显示这些内容,点击 JUnit标签(在底部的左边)。
 
          Image 
                    图 2. JUnit中失败的测试
   
    很好!的却失败了。现在我们来建立被测试代码:在包资源管理器窗口的 ProjectWithJUnit标题上右击,选择 新建 -> 。选择类名,我们已经假设了它叫 HelloWorld,然后直接点击 完成。为 HelloWorld.java填入下列代码:
        public class HelloWorld {
            public String say() {
                return("Hello World!");
            }
        }
       
    这段代码很简单,甚至不需要注解,我们再来看看结果。按照上面描述过的方式,在 JUnit的窗口中显示了一个绿条,参看图 3。绿条证明测试成功。

 

            Image

                     图 3. JUnit中成功的测试
                              
    现在,我们想再让测试失败一次,但原因不同。这有助于展示 JUnit测试中不同的报错信息。修改 assertEquals()代码,把“ Hello World!”变成“ Hello Me!”。当再次运行 JUnit时,结果变成了红条,在 JUnit窗口的底部输出了失败原因,参看图 4。
 
            Image
                    图 4. JUnit中的 ComparisonError
                             
    最后,我想说一下关于测试是开发过程中的必要部分的话题。测试代码一直是开发中的重要部分。经过近几年的发展,已得到了很大的提高,这要归功于强大的理论研究(比如“ expectations-based development”等等),和快速发展的测试工具包,还有测试过程的改进。如果你对这篇文章感兴趣,那请你花一些时间来正式的学习一下测试理论吧,这对你的工作很有用。
    关于作者:
    Alexander Prohorenko 一名 UNIX系统管理员、网络安全管理员。
    Olexiy Prohorenko    一名 Java开发者居住在乌克兰的 Dniepropetrovsk。  
    译者:Rosen Jiang 
    译文原址: http://blog.csdn.net/rosen



Using JUnit With Eclipse IDE

by Alexander Prohorenko and Olexiy Prohorenko
02/04/2004


This article is going to introduce you to JUnit, a tool for project testing and debugging. After introducing the theory of test-driven development, we'll move on to a step-by-step explanation of how you can create your JUnit tests with the help of the popular Eclipse IDE. We'll show how something as simple as a Hello World program can be exposed to a JUnit test.

Many books have already been written about automated testing, but very few of them pay attention to the question of how to organize such tests. As more tests are written, it becomes harder to know where to put a test or even what to call it. This has become a significant issue with the rise of test-driven development (TDD), which has been popularized by Extreme Programming (XP). You can think of TDD as "development through testing."

The major provisions of TDD are:

  • Before writing any code fragment, an automated test must be written to check the functioning of this code. Since the code does not exist yet, it initially fails the test.
  • After the test begins to pass, duplicate code must be removed.
Such an approach can be used by any programmer and does not require the use of a specific methodology. But before we get into writing tests, it would be desirable to first look at how to organize the automated tests.

There several different kinds of tests we should consider:

Related Reading


  • Unit tests: These serve to check the correctness of several modules (i.e., classes). If the object needs access to some external da ta source, like a database, these are simulated with mock objects, but on ly in cases in which re-creating the actual da ta source would be difficult in a test environment.

  • Customer's tests: These are functional, system, and acceptance tests. All of them check the beha vior of the system as a whole. In the XP methodology, these tests are written by the customer, given the program skeleton.

  • Integration tests: These are like a cross between the customer tests and unit tests. Integration tests help test the interaction of several levels of the application. Typically, mock objects are not used in integration testing, which may increase testing time. Also, integration tests often demand the presence of a special test environment, such as a database seeded with test da ta. Integration tests may also use special external libraries. An example of such a library for the integration of J2EE applications is Cactus. Explanation of these tests is going beyond of this article, and requires much detailed theory information, so you just take it as information that such kind of tests exists.

  • Developer's tests: These are just tests that developers use to verify whole co de, new pieces of co de, and/or new functions. For each developer, it is imp ortant to generate new tests to check co de whenever possible. Organizing these tests can be as imp ortant as organizing the co de base itself.

For the rest of this article, when I say "test," I will mean developer's test.

During development, a programmer sometimes asks himself or herself: is there a test for the given beha vior of the system and if it exists, where it can be found? A classic example is basic bug fixing, in which the mistake is found, but not by automated tests. The sequence of events that results from this situation might be:

  1. Look for a test for the given functionality (it's probable that the test is already written, but contains a mistake).
  2. If such test is not present, or it does not cover a situation in which there is a mistake, we will need to write a new test that reveals it.
  3. Now we need to be convinced that the new test does not pass.
  4. Fix the bug.
  5. Run the test.
  6. Confirm that it passes.
Certainly, variations of this process are possible, but the idea should be clear: you on ly correct a mistake when you have a test that reveals the mistake.

Now, let's consider how a developer would solve this situation. To search through existing functionality tests:

  • We can take advantage of certain integrated development environments (IDEs) that allow us to search for places in which corrected classes and methods are used.
  • Create a known error situation and inspect what fragment of code is in error.
  • Last but not least, write the test and place it in one of the existing test classes. If you make a mistake arranging your test and duplicate test code, hopefully you or one of your colleagues will eventually notice the duplication and correct it.
We are almost ready to create our test, so now we have to choose a name for our test. You could say, "It's not even a problem: just put the word "Test" before your class name, and that's it!" But not so fast! Let me just show how this approach can run into trouble:

  • When using TDD, the class or method to be tested may not exist yet.
  • It's also possible that one test can cover several methods, or even several classes.
These are just the most common problems; there are many more.

Let me offer on e recommendation on naming your tests: the name of a test class should convey that this class is a test class, and indicate what exactly it checks, whether or not it repeats the name of a tested class. That's easy. Don't worry if such a name turns out too long or ugly. It describes itself, and that is the idea.

We will create our first test with the help of the JUnit tool in the Eclipse IDE. I assume that you have already downloaded a recent version of this product, but if not, you can always get it from the official site. We need JUnit, which you can download from its official site, too. Download it and unzip somewhere on your disk, where you are keeping your Java libraries.

Run Eclipse IDE. We will create a new workplace project, so click File -> New -> Project, then choose Java and click Next. Type in a project name -- for example, ProjectWithJUnit. Click Finish. The new project will be generated in your IDE. Let's configure our Eclipse IDE, so it will add the JUnit library to the build path. Click on Project -> Properties, select Java Build Path, Libraries, click Add External JARs and browse to directory where your JUnit is stored. Pick junit.jar and click Open. You will see that JUnit will appear on your screen in the list of libraries. By clicking Okay you will force Eclipse to rebuild all build paths.

We are ready to start developing our "Hello World" example. Let's follow TDD rules and create the test even before we have any kind of co de. For the sake of having somewhere to start, we will assume that our future co de class will be named HelloWorld and that it will have the method say(), which will return some String value ("Hello World," for example).

To create such a test, right-click on the ProjectWithJUnit title, select New -> Other, expand the "Java" selection, and choose JUnit. On the right column of the dialog, choose Test Case, then click Next. This is illustrated by Figure 1.


Figure 1. Creating a JUnit test in the Eclipse IDE

Type in the name of our yet-to-be written class HelloWorld into the Test class field, and choose a name for our Test case -- for example, TestThatWeGetHelloWorldPrompt (yes, it looks too long, but it clearly indicates what it does.) Click on Finish.

The co de for TestThatWeGetHelloWorldPrompt.java is as follows:

import junit.framework.TestCase;  public class TestThatWeGetHelloWorldPrompt     extends TestCase {     public TestThatWeGetHelloWorldPrompt(         String name) {         super(name);     }     public void testSay() {         HelloWorld hi = new HelloWorld();         assertEquals("Hello World!", hi.say());     }     public static void main(String[] args) {         junit.textui.TestRunner.run(             TestThatWeGetHelloWorldPrompt.class);     } }
This co de is not complex; it's just a bit unusual. However, let's examine it in detail. We extend JUnit's TestCase class, which is defined in JUnit's javadocs as "a fixture to run multiple tests." JUnit also has TestSuite, which is a set of related test cases, but we will not work with in this article.




To create our own simple test case, we need to follow these steps:

  1. Create an instance of junit.framework.TestCase.
  2. Define tests that return void and whose name begins with the string "test" (such as testWasTransactionSuccessful(), testShow(), etc.).

TestThatWeGetHelloWorldPrompt.java meets both of these criteria: it subclasses TestCase and has a method called testSay(). This method uses an assertEquals() call, which compares the value which we expect to receive against the value returned by say().

The main() method is used to run the tests and present their output. JUnit's TestRunner executes our tests, and provides both graphical and textual output. We use the textual version because that's what Eclipse IDE supports and it's absolutely suitable for us. On ce executed, the textual version of the test shows the result as text output and Eclipse IDE uses that to create its own graphic presentation.

So, according TDD provisions, on ce we run our test we should see that it failed. Let's try. Click Run -> Run as -> JUnit Test (remember that TestThatWeGetHelloWorldPrompt.java should be highlighted in Package Explorer). In the left window, instead of Package Explorer, you will see the JUnit window, which shows a red bar, the failed tests, and details of those failures, as seen in Figure 2. If you do not automatically see it, just click on JUnit label (on the bottom left), which is on e of the layers of this screen.


Figure 2. Failed test in JUnit

Perfect! It really fails. Now we can create working co de in our project: right-click the ProjectWithJUnit title in the left Package Explorer window, then choose New -> Class. Choose a name for the class — we've assumed it to be HelloWorld. Do not check off any of checkboxes on the bottom of the dialog window, just click Finish. Below is the co de for HelloWorld.java:

public class HelloWorld {     public String say() {         return("Hello World!");     } }
It's very simple and merits no commentary. So let's test it and see the results. Run our test the same way as described above, and in the left JUnit window you will see a green bar, as seen in Figure 3. The green bar means that our test was successful.


Figure 3. Successful test in JUnit

Now we want to try to make it fail on ce again, but for a different reason. This will help show how JUnit test covers and reports different errors. Edit the assertEquals() to change the expected return value from "Hello World!" to, for example, "Hello Me!". When you run this JUnit test again, the bar will be red, and at the bottom of the left JUnit window you will see an explanation of what failed, as illustrated by Figure 4.


Figure 4. ComparisonError running JUnit

In conclusion, I would like to mention a few thoughts about testing as a necessary part of the development process. Testing co de was always an integral part of any development. But it has been advanced over the last few years, thanks to powerful methodologies (such as "expectations-based development," etc.), accelerated testing toolkits, and the development of better testing processes. If you have found this article interesting, take some time to study formal testing methodology, and use it in your work.

Alexander Prohorenko is a certified professional, who holds Sun Certified System Administrator and Sun Certified Java Programmer certifications.

Olexiy Prohorenko is a燬un Certified Enterprise Architect whose areas of interests include Web software architecture and development of software爓ith frequently changing requirements.


Return to ONJava.com.

Copyright © 2006 O'Reilly Media, Inc.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值