关闭

有关Junit的多线程测试

发表于:2007-10-29 13:36

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

 作者:未知    来源:网络转载

        Junit和许多开源软件项目集成在一起,但是Junit执行多线程的单元测试有一些问题。这篇文章介绍Junit的一个扩展类库―――GroboUtils,这个类库被设计为来解决这些问题,并且使在Junit中进行单元测试成为可能。对Junit和线程有一个基本的理解是有好处的,但对于本篇文章的读者来说不是必需的。

介绍
        如果你已经在一个开源的Java项目上工作,或者读了许多有关“极限编程”和其它“快速开发模式”的书籍,那么,你很有可能已经听说过有关Junit的事情。它是由Erich Gamma和Kent Beck编写的,Junit是一个Java的自动测试的框架,它允许你为你的软件定义的“单元测试”―――不管是测试程序还是功能代码,通常都是基于方法调用方法的。

        Junit能在很多方面帮助你的开发团队―――在一些文章中已经包含了很多这方面的介绍。但从一个开者到另一个开发者,Junit实际上只专箸于两件事:

        1、它强制你使用自己的代码。你的测试代码只是作为你的产品代码的客户端,从客户端的描述所获得的对你的软件的了解,能够帮助你标识出在API中的错误以及怎样改进代码,使其最终达到可以使用的目的。

        2、它会给你对软件中改变带来信心,如果你的测试用例被中断,你就是立刻知道错误。在一天工作结束的时候,如果测试提示是绿色的,则代码是正确,你可以自信的检查它。

        但是Junit不是解决所有软件测试中问题,第三方的扩展类库,例如HttpUnit,JwebUnit,XMLUnit等,已经认识到这些框架中不足,并且通过添加功能弥补不足,这些不足之一就是Junit不包含多线程的单元测试。

        在这篇文章中,我们会看到一个很少有人知道的解决这个问题的扩展类库。我们通过建立Junit框架开始,并且运行一个例子来展示Junit在线程没试中的不足。在我们认识了Junit在线程测试方面的不足之后,我们通过一个使用GroboUtils框架的例子来讨论GroboUnitls

线程回顾

        对于那些不熟悉线程的人来说,在这一点上是非常不安的(一点都不夸大),离开你的系统,我们将对线做一个简单的介绍。线程允许你的软件有多个任务,也就是说可以同时可做两件事情。
        在Khalid Mugal和Rolf Rasmussen的书(A Programmer's Guide to Java Certification)中,对线程做了下面这样的简短描述:
        一个线程是一个程序中的可执行单元,它是被独立执行的。在运行时,在程序中的线程有一个公共的内存空间,因此,能够共享数据和代码;也就是说,它们是轻量级的。它也共享正在运行程序的进程。
        Java 线程使运行时环境异步,它允许不同的任务同时被执行。(p.272)


        在web应用程序中,许多用户可能同时发请求给你的软件。当你写单元测试对你的代码进行压力测试时,你需要模拟许多并发事件,如果你在开发健壮的中间件,这样做是尤其重要的。对于这些组件,使用线程测试是一个好的想法。

        不幸的是,Junit在这方面是不足的。

有关Junit和多线程测试的问题

        如果你想验证下列代码,你需要下载并安装Junit。按着指示去做,以便能够在Junit的网站能够找到它。不要过分追求细节,我们将简要的介绍Junit是怎样工作的。要写一个Junit的测试,你必须首先创建一个扩展于junit.framework.TestCase(Juint中的基本测试类)的测试类。
        Main()方法和suite()方法被用启动测试。无论是从命令行还是IDE集成开发环境窗口,必须确保junit.jar在你的CLASSPATH环境变量里指定。然后为BadExampleTest.Class类编译运行下列代码:
import junit.framework.*;
public class BadExampleTest extends TestCase {
    // For now, just verify that the test runs
    public void testExampleThread()
            throws Throwable {
        System.out.println("Hello, World");
    }
    public static void main (String[] args) {
        String[] name =
            { BadExampleTest.class.getName() };
        junit.textui.TestRunner.main(name);
    }
    public static Test suite() {
        return new TestSuite(
            BadExampleTest.class);
    }
}

        运行BadExampleTest来验证所建立的每一件事情的正确性。一旦,main()被调用,Junit框架将自动的执行任意一个用“test”开关命名的方法。继续并试着运行测试类。如果你正确的做了每一件事,它应该在输出窗口打印出“Hello World”。
        现在,我们要给程序添加一个线程类。我将通过扩展java.lang.Runnable接口来做这件事情。最后,我们将改变策略,并且扩展一个使线程自动创建的类。
        在DelayedHello的构造器中,我们创建一个新的线程并且调用它的start()方法。
import junit.framework.*;
public class BadExampleTest extends TestCase {
    private Runnable runnable;
public class DelayedHello
        implements Runnable {
        private int count;
        private Thread worker;
        private DelayedHello(int count) {
            this.count = count;
            worker = new Thread(this);
            worker.start();
        }
        public void run() {
            try {
                Thread.sleep(count);
                System.out.println(
                "Delayed Hello World");
            } catch(InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

    public void testExampleThread()
            throws Throwable {
        System.out.println("Hello, World");       //1
        runnable = new DelayedHello(5000);        //2
        System.out.println("Goodbye, World");     //3
    }
    public static void main (String[] args) {
        String[] name =
            { BadExampleTest.class.getName() };
        junit.textui.TestRunner.main(name);
    }
    public static Test suite() {
        return new TestSuite(
            BadExampleTest.class);
    }
}

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

关注51Testing

联系我们

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

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

沪ICP备05003035号

沪公网安备 31010102002173号