GroboUtils之多线程测试

Junit作为java自动化测试利器,在java软件开发方面有着强大的功能和便利。通过大量的单元测试,可以方便的定位错位,而且可以提高自己对代码的信心。单元的颗粒度可以小到是一个函数,也是大到是一个类,甚至更大,但是,在单元测试时,由于junit的设计,它对于runnable的对象是忽略的,所以,在我们的测试过程中,对于多线程的测试就变得困难和不可行。但是,在有些项目中,对多线程的测试又是必须的,难以两全么?现在有了 groboutils,这一切就变得轻松方便了。
    在一些单元测试时,我们有可能需要调用一些类的线程,但是,在junit原有的模型上,要么 runnable对象被忽略了,要么就得调用它的run()方法,但是,这样的调用也就失去了并发性,在想要查看线程之间的调度时,这样的功能是不够的。
    首先来看一段简单的代码,我们有个类来计算pi,还有个去查看即时的pi值。

//class 'calculate pi'
public class pi extends Thread {
        volatile double pi;
        public double getPi() {
                return this.pi;
        }
        public void setPi(double pi) {
                this.pi = pi;
        }
        public void run() {
                calPI();
        }
        private double calPI() {
                boolean negative = true;
                for (int i = 3; i < Long.MAX_VALUE; i += 2) {
                        if (negative)
                                pi -= (1.0 / i);
                        else
                                pi += (1.0 / i);
                        negative = !negative;
                }
                pi += 1.0;
                pi *= 4.0;
                return this.pi;
        }
        public pi() {
                start();
        }
}
//class view the value of pi
public class observer extends Thread {
        pi pi;
        observer(pi pi) throws InterruptedException {
                this.pi = pi;
                System.out.println("Start to calculate pi");
                start();
        }
        public void run() {
                while (true) {
                        double zz = pi.pi;
                        try {
                                Thread.sleep(1000);
                                System.out.println((zz + 1) * 4);
                        } catch (InterruptedException e) {
                                e.printStackTrace();
                        }
                }
        }
}
然后,我们进行junit测试。

//测试类
import junit.framework.TestCase;
public class observerTest extends TestCase {
        protected void setUp() throws Exception {
        }
        protected void tearDown() throws Exception {
        }
        public void testObserver() throws InterruptedException {
                pi temp = new pi();
                new observer(temp);
        }
}
    很不幸,我们发现,在构造函数初始化时,它忽略了start(),就直接结束了。这显然不是我们想要的结果,在junit中,对于线程,显然是不支持的。好在有了groboutils,这一些就变得方便和轻松了。作为在junit的框架下面的扩展,如果想要使用支持线程的测试,线程要继承 TestRunnable这个类,并且重载这个类的runTest方法来代替原来的run();进行多线程测试时,通过 MultiThreadedTestRunner来控制线程的启动,先给出改写后的类。


//改写后的pi计算

import net.sourceforge.groboutils.junit.v1.TestRunnable;
public class testpi extends TestRunnable {
        volatile double pi;
        public double getPi() {
                return this.pi;
        }
        public void setPi(double pi) {
                this.pi = pi;
        }
        public void runTest() {
                calPI();
        }
        private double calPI() {
                boolean negative = true;
                for (int i = 3; i < Long.MAX_VALUE; i += 2) {
                        if (negative)
                                pi -= (1.0 / i);
                        else
                                pi += (1.0 / i);
                        negative = !negative;
                }
                pi += 1.0;
                pi *= 4.0;
                return this.pi;
        }
        public testpi() {
        }
}

//改写后的ob
import net.sourceforge.groboutils.junit.v1.TestRunnable;
public class testob extends TestRunnable {
        testpi pi;
        testob(testpi pi) throws InterruptedException {
                this.pi = pi;
                System.out.println("Start to calculate pi");
        }
        public void runTest() {
                while (true) {
                        double zz = pi.pi;
                        try {
                                Thread.sleep(1000);
                                System.out.println((zz + 1) * 4);
                        } catch (InterruptedException e) {
                                e.printStackTrace();
                        }
                }
        }
}


//改写后的测试类
import net.sourceforge.groboutils.junit.v1.MultiThreadedTestRunner;
import net.sourceforge.groboutils.junit.v1.TestRunnable;
import junit.framework.TestCase;

public class groboutil_test1 extends TestCase {
        public void testobserver() throws Throwable {
                TestRunnable tr1,tr2;
              
                tr1=new testpi();
                tr2=new testob((testpi)tr1);
                TestRunnable[] trs={tr1,tr2};
                MultiThreadedTestRunner mttr = new MultiThreadedTestRunner(trs);
                mttr.runTestRunnables();
        }
}
    可以看到,这样,程序又可以正常的启动测试了。通过在testrunnable数组里面任意调用需要的线程, MultiThreadedTestRunner会自己等待所有的线程执行完毕退出后才继续,所以,我们不必自己调用线程的start(),来启动线程,而且交给 MultiThreadedTestRunner来统一调度,它会统一为线程启动进行异步控制。对于测试者而言,只需把注意力放在自己关注的单元测试上。并且,它还提供了delay(),isDone()等方法,进一步方便测试者的调试。
    有了GroboUtils,多线程测试从此变得简单而快乐。
    GroboUtils链接:http://groboutils.sourceforge.net/   

你可能感兴趣的:(多线程,.net,软件测试,单元测试,JUnit)