尝试翻译JRUnit的文档(三)

翻译 2007年10月10日 20:20:00
     这一章太多了,分两次
    第三章 实例
    这一章主要包括JRUNIT项目中的一些例子,这些例子主要是关于C/S架构的测试。基于一组相同的、基本的客户端和服务器的代码,利用socket从客户端发送一个字符串到服务器,服务器再返回一个固定的字符串给客户端,这一章所有的例子都会籍此代码来展示microbenchmark和jrunit的不同。(All the samples illustrate the different features of microbenchmark and jrunit using the same base client and server base code which uses a socket to send a String to the server from the client, which is then returned a static String from the server. )所有的实例均可在IDE中编译和运行,有些还可以通过JRUNIT根目录下的ant构建脚本来运行。之所以只有部分才能在ant脚本中,是因为他们可以被完全自动化(接下来将会解释这一点)。还有一点需要注意的是,下面每个实例所在章节的标题,都与org.jboss.jrunit.sample这个包相关,这些例子都可以在这个包所在路径下找到。
    
    basic
    第一个C/S测试的例子在org.jboss.jrunit.sample.basic包中,包括SimpleServerTest和SimpleServerTest。后面介绍各个不同特色的test case都是基于这两个test的。SimpleClientTest是一个基本的JUNIT test case,包含两个test方法,testClientCall()和testFailure{}方法
    //代码
    public class SimpleClientTest extends TestCase
    {
        private String address = "localhost";
        private int port = 6700;
        private Socket socket = null;
        private ObjectOutputStream oos;
        private ObjectInputStream objInputStream;
        public void testClientCall() throws Exception
        {
            getSocket();
            oos.writeObject("This is the request from " + Thread.currentThread().getName());
            oos.reset();
            oos.writeObject(Boolean.TRUE);
            oos.flush();
            oos.reset();
            Object obj = objInputStream.readObject();
            objInputStream.readObject();
            assertEquals("This is response.", obj);
        }
        
        public void testFailure()
        {
            fail("This is a check to make sure failures reported.");
        }
        private void getSocket() throws IOException
        {
            if(socket == null)
            {
                try
                {
                    socket = new Socket(address, port);
                    BufferedOutputStream out = new BufferedOutputStream(socket.getOutputStream());
                    BufferedInputStream in = new BufferedInputStream(socket.getInputStream());
                    oos = new ObjectOutputStream(out);
                    objInputStream = new ObjectInputStream(in);
                }
                catch(IOException e)
                {
                    e.printStackTrace();
                }
            }
            else
            {
                oos.reset();
                oos.writeByte(1);
                oos.flush();
                oos.reset();
                objInputStream.readByte();
            }
        }
    }

    testClientCass方法会打开一个socket连接到服务器,发送一条字符串过去,然后检查从服务器返回的字符串,看看它的值是不是和预期的一样(通过JUNIT的assert),而testFailure方法只是使用一个junit的fail assertion
    SimpleServerTest也是一个基本的JUNIT test case,在它的setUp方法里(一个独立的线程内)建立了一个socket服务器,接收来自客户端的请求并返回固定的字符串。SimpleServerTest也有一个test方法,叫做testRequestCount,这个方法每三秒打印出接受到的请求数目
    //代码
    public class SimpleServerTest extends TestCase //ServerTestCase
    {
        private int serverBindPort = 6700;
        private int backlog = 200;
        private ServerSocket serverSocket;
        private InetAddress bindAddress;
        private String serverBindAddress = "localhost";
        private int timeout = 5000; // 5 seconds.
        private boolean continueToRun = true; // flag to keep the server listening
        private int requestCounter = 0;
        protected void setUp() throws Exception
        {
            System.out.println("SimpleServerTest::setUp() called.");
            bindAddress = InetAddress.getByName(serverBindAddress);
            serverSocket = new ServerSocket(serverBindPort, backlog, bindAddress);
            // this was done inline since TestCase already has a void parameter run() method
            // so could not create a run() method for the Runnable implementation.
            new Thread()
            {
                public void run()
                {
                try
                {
                    startServer();
                }
                catch(Exception e)
                {
                    e.printStackTrace();
                }
                }
            }.start();
        }
        
        public void testRequestCount()
        {
            while(continueToRun)
            {
                try
                {
                    Thread.currentThread().sleep(3000);
                }
                catch(InterruptedException e)
                {
                    e.printStackTrace();
                }
                System.out.println("Requests taken: " + requestCounter);
            }
            assertEquals(30, requestCounter);
        }
        
        protected void tearDown() throws Exception
        {
            continueToRun = false;
            System.out.println("Tearing down. Processed " + requestCounter + " requests"
            if(serverSocket != null && !serverSocket.isClosed())
            {
                serverSocket.close();
                serverSocket = null;
            }
        }
        
        private void startServer()
        {
            while(continueToRun)
            {
                try
                {
                    Socket socket = serverSocket.accept();
                    socket.setSoTimeout(timeout);
                    BufferedOutputStream bos = new BufferedOutputStream(socket.getOutputStr
                    BufferedInputStream bis = new BufferedInputStream(socket.getInputStream
                    ObjectOutputStream oos = new ObjectOutputStream(bos);
                    oos.flush();
                    ObjectInputStream objInputStream = new ObjectInputStream(bis);
                    processRequest(objInputStream, oos);
                    while(continueToRun)
                    {
                        acknowledge(objInputStream, oos);
                        processRequest(objInputStream, oos);
                    }
                }
                catch(IOException e)
                {
                    System.out.println("Done processing on client socket.");
                }
                catch(ClassNotFoundException e)
                {
                }
            }
        }
...

    这段代码反映了以C/S模式进行junit测试的一个问题。客户端在它运行整个测试期间需要一个服务器来接收它的请求。服务器则按照junit的传统模式,先set up,然后test,最后tear down。当服务器和客户端都跑起来时,SimpleClientTest的testClientCall将会测试通过,但是SimpleServerTest的testRequestCount却永远不会结束,tearDown也将没法被调用
    如果想停止SimpleServerTest,它所在的线程就必须被杀死。如果改变SimpleServerTest的testRequestCount方法,使得它不再循环,那运行SimpleServerTest的测试就可能在SimpleClientTest有机会调用它之前就结束了,导致testClientCall失败
    
    decorated
    虽然这个实例不会直接用到jrunit的特性,但它却显示了使用基准修饰符(benchmark decorator)的好处。这个实例对刚才的SimpleClientTest和SimpleServerTest作了少许修改。
    //代码
    public static Test suite()
        {
            return new ThreadLocalDecorator(SimpleClientTest.class, 3, 10, 0, true);
        }
        public void testClientCall() throws Exception
        {
        // start benchmark tracking
        ThreadLocalBenchmark.openBench("ClientCall");
        ThreadLocalBenchmark.openBench("GetSocket");
        getSocket();
        ThreadLocalBenchmark.closeBench("GetSocket");
        /**
        * Uncomment this to see that is the same object, thread, and socket for each loop,
        * but will be different for each thread as specified to the test decorator. This
        * is based on the values passed to JunitThreadDecorator (or one of it's subclasses)
        * for the numberOfThreads and loop parameter values.
        */
        /**
        *    把下面的注释去掉,就可以看出每次循环都是相同的对象、线程和socket,但不同线程之间是不同的,
        *    这跟传给JunitThreadDecorator(或者它的子类)构造器参数:numberOfThreads和loop的值有关
        */
        //System.out.println(hashCode() + " - " + Thread.currentThread().getName() + " -" + socket.hashCod
        oos.writeObject("This is the request from " + Thread.currentThread().getName());
        oos.reset();
        oos.writeObject(Boolean.TRUE);
        oos.flush();
        oos.reset();
        Object obj = objInputStream.readObject();
        objInputStream.readObject();
        assertEquals("This is response.", obj);
        ThreadLocalBenchmark.closeBench("ClientCall");
    }
    
    修改了SimpleClientTest后,增加了一个suite方法,这个方法将返回一个org.jboss.jrunit.decorators.ThreadLocalDecorator类的新实例。在本例中,传递给decorator的参数使它在运行org.jboss.jrunit.sample.decorated.SimpleClientTest这个test case时,使用三个线程数,每个线程十次循环,没有延时(你可以参考ThreadLocalDecorator这一节来获得更多关于ThreadLocalDecorator的信息)
    
    这意味着当SimpleClientTest运行时,会有三个(线程)实例被创建,每个线程都会运行所有的test方法十次。SimpleClientTest类的testClientCall方法也加了几行代码,用于标记(mark)某个benchmark的开始和结束。在这里,ClientCall和GotSocket这两个benchmark在方法的开头处开始记录
    GotSocket基准在进行完getSocket方法的全部调用后中止,而ClientCall基准在方法末尾中止,目前SimpleServerTest并没有被修改,因此服务器代码一次只接受一个连接,处理完请求后,连接关闭,然后再处理下一个连接。
    要运行这个实例,首先启动org.jboss.jrunit.sample.basic.decorated.SimpleServerTest,然后启动org.jboss.jrunit.sample.decorated.SimpleClientTest 。客户端运行完毕后,将服务器停止,在客户端控制台底部会有类似这样的一行:
    
    SubBenchmarks: Benchmark:ClientCall Executions:30 Time:15311 SubBenchmarks: Benchmark:GetSocket Executions:30 Time:15191
    
    这表明三个线程分别对testClientCall和getSocket方法运行十次花了多少时间。现在,把SimpleServerTest类的setUp方法中循环体内的注释去掉(译注:在SimpleServerTest中根本找不到所谓的循环体,从下文看估计是在new Thread外面有一个循环,用于生成多个thread),那样就会有三个可用的线程来接收客户端发来的请求了(请千万不要向我抱怨说服务器不该这样编码的....别太认真,这只是演示而已:))。编译并再次运行,你应该会得到像这样的结果:
    
    SubBenchmarks: Benchmark:ClientCall Executions:30 Time:130 SubBenchmarks: Benchmark:GetSocket Executions:30 Time:30
    
    这个结果表明,把服务器改成多线程后可以并发地接收和处理所有客户端的请求,因此客户端的方法调用比原来快乐100多倍。

尝试翻译JRUnit的文档(二)

第二章——JRunit的工作原理C/S测试       首先要解决的是服务器端测试的生命周期问题,因为它需要从junit生命周期管理的默认行为中分离出来(单独讨论)       首先需要有一种方法来通...
  • wangchengsi
  • wangchengsi
  • 2007-10-07 15:31:00
  • 606

尝试翻译JRUnit的文档(四)

继续上次的....clientserver    下一个例子是关于在junit框架下运行C/S测试引发的一些问题,以及jrunit是如何解决这些问题的,相关代码位于org.jboss.jrunit.s...
  • wangchengsi
  • wangchengsi
  • 2007-10-15 22:50:00
  • 619

尝试翻译JRUnit的文档(一)

最近开始接触JBOSS IDE,想借此学习J2EE,在查资料时,偶尔接触到jboss社区的一个开源项目——JRUnit,是Junit的一个扩展,貌似功能还挺强大的。百度一下,发现相关资料少之又少,遂冒...
  • wangchengsi
  • wangchengsi
  • 2007-10-04 20:47:00
  • 601

尝试翻译JRUnit的文档(五)

 第四章 Configuration配置    TestDriver提供了多个可以重载的方法,用来改变默认配置,比如下面的例子:        /**    * How long to wait fo...
  • wangchengsi
  • wangchengsi
  • 2007-10-15 22:52:00
  • 562

rfc文档(中文翻译)目前最全的

  • 2009年03月18日 11:25
  • 3.48MB
  • 下载

和菜鸟一起学产品之产品经理的三大文档

  • eastmoon502136
  • eastmoon502136
  • 2013-12-17 18:39:28
  • 5644

sqlmap帮助文档(配合实践翻译)

本文链接:http://blog.csdn.net/u012763794/article/details/52638931 用过sqlmap,也用过不少功能了,为了更加了解这个工具,决定翻译一下...
  • u012763794
  • u012763794
  • 2016-09-23 23:40:18
  • 2303

python官方文档(自翻译)

python官方文档(自翻译)The Python TutorialPython 是一种简单易学且功能强大的编程语言。它具有高效且高层次的数据结构和简单有效面向对象编程方法。Python优雅的语法和动...
  • broken_promise
  • broken_promise
  • 2017-08-23 10:33:10
  • 156

Spring官方文档翻译(1~6章)

Spring官方文档翻译
  • tangtong1
  • tangtong1
  • 2016-05-05 22:26:39
  • 29275

用谷歌浏览器将英文文档翻译成中文的方法(无字数限制)

思路:用谷歌翻译文档有5000字的限制,但是翻译网页就不会有字数限制。需要的软件:Adobe Acrobat 、谷歌浏览器提供下载地址Adobe Acrobat XI Pro: https://pan...
  • fuzimango
  • fuzimango
  • 2017-08-20 01:09:24
  • 6655
收藏助手
不良信息举报
您举报文章:尝试翻译JRUnit的文档(三)
举报原因:
原因补充:

(最多只允许输入30个字)