使用GroboUtils進行jUnit的多線程測試

使用GroboUtils進行jUnit的多線程測試

 

jUnit不支持多線程測試(具體表現爲,在@Test標記的方法中啓動多線程測試,這是多線程中的Assert方法失效

具體原因是jUnit執行器執行的時候,執行線程很快退出,在多線程中還沒有調用Assert的時候主線程就退出了,

而且,貌似jUnit也不會檢測其他線程中調用Assert方法,即使其他線程中Assert方法失敗了,

總的測試結果往往還是顯示成功),

 

需要借用GroboUtils(http://groboutils.sourceforge.net/downloads.html)

GroboUtils是一個工具集合,裏面包含各種測試工具,這裏使用的是該工具集中的jUnit擴展.

 

這裏使用的是GroboUtils v5版本,下載 Complete package:GroboUtils-5.zip

解壓後 使用 GroboUtils-5\lib\core\GroboTestingJUnit-1.2.1-core.jar 這個即可.

 

GroboUtils 工具集中的jUnit擴展 的文檔頁面:

http://groboutils.sourceforge.net/testing-junit/index.html

 

示例(來自: http://mushiqianmeng.blog.51cto.com/3970029/897786):

 

/** 
     * 多線程測試用例 
     *  
     * @author lihzh(One Coder) 
     * @date 2012-6-12 下午9:18:11 
     * @blog http://www.coderli.com 
     */ 
    @Test 
    public void MultiRequestsTest() { 
                // 構造一個Runner 
        TestRunnable runner = new TestRunnable() { 
            @Override 
            public void runTest() throws Throwable { 
                // 測試內容 
                // 可以在這裏直接調用Assert的各種方法,因爲TestRunnable類是繼承自Assert的
            } 
        }; 
        int runnerCount = 100; 
                //Rnner數組,想當於併發多少個。 
        TestRunnable[] trs = new TestRunnable[runnerCount]; 
        for (int i = 0; i < runnerCount; i++) { 
            trs[i] = runner; 
        } 
                // 用於執行多線程測試用例的Runner,將前面定義的單個Runner組成的數組傳入 
        MultiThreadedTestRunner mttr = new MultiThreadedTestRunner(trs); 
        try { 
                        // 開發併發執行數組裏定義的內容 
            mttr.runTestRunnables(); 
        } catch (Throwable e) { 
            e.printStackTrace(); 
        } 
    } 

 

 

備忘: 

JUnit best practices

http://www.javaworld.com/article/2076265/testing-debugging/junit-best-practices.html?page=3

 

主要關注3個類:TestRunnable,TestMonitorRunnable,MultiThreadedTestRunner,全部來自包:

net.sourceforge.groboutils.junit.v1.MultiThreadedTestRunner.

 

(1) TestRunnable 抽象類,表示一個測試線程,實例需要實現該類的runTest()方法,在該方法中寫自己用的測試代碼.

    該類繼承了jUnit的junit.framework.Assert類,所以可以在TestRunnable中使用各種Assert方法

    (可惜因爲GroboUtils使用的jUnit版本較老,且久未更新,新版本的jUnit中已經不推薦使用這個類的方法了).

    

    該類實現了Runnable,在run方法中調用抽象方法runTest().

 

Doc中介紹    

public abstract class TestRunnable

extends junit.framework.Assert

implements java.lang.Runnable

Instances of this class only execute in the runTestRunnables method of the MultiThreadedTestRunner class. 

TestCases should define inner classes as a subclass of this, implement the runTest() method, 

and pass in the instantiated class as part of an array to the runTestRunnables method. 

Call delay( long ) to easily include a waiting period. 

This class allows for all assertions to be invoked, 

so that subclasses can be static or defined outside a TestCase. 

 

If an exception is thrown from the runTest() method, 

then all other test threads will terminate due to the error.

 

The runTest() method needs to be responsive to InterruptedException, resulting from the 

owning MultiThreadedTestRunner interrupting the thread in order to signal the early 

termination of the threads. The InterruptedExceptions may be propigated outside the runTest() 

implementation with no harmful effects. Note that this means that InterruptedExceptions 

are part of the framework, and as such carry information that your runTest() 

implementations cannot override; in other words, don't let your test 

propigate an InterruptedException to indicate an error.

 

Tests which perform a set of monitoring checks on the object-under-test should 

extend TestMonitorRunnable, since monitors run until told to stop. 

The Thread.stop() command will be sent with a MultiThreadedTestRunner.TestDeathException.

 

(2)   MultiThreadedTestRunner 

 這個類相當與一個ExecuteService,可以用來執行 TestRunnable,構造函數需要傳入TestRunnable數組,

 表示需要測試的線程. 

 調用MultiThreadedTestRunner.runTestRunnables() 方法啓動測試線程,開始執行測試.

 這個方法默認讓測試線程TestRunnable的run方法最多運行1天,也可以調用

 MultiThreadedTestRunner.runTestRunnables(long maxTime) 這個方法,然測試線程TestRunnable

 最多執行 maxTime 毫秒.如果超過maxTime毫秒之後,TestRunnable還沒有執行完畢,則TestRunnable

 會被中斷,並且MultiThreadedTestRunner 會拋出異常,

 導致測試失敗fail("Threads did not finish within " + maxTime + " milliseconds.").

 

 每個TestRunnable中runTest需要能夠控制自己在什麼時間自己結束自己,精確控制測試時間,不要利用

 上面的maxTime.

 

 另外,有上面Doc文檔中:

 If an exception is thrown from the runTest() method, 

then all other test threads will terminate due to the error.

可知,假如有一個TestRunnable的runTest()方法中拋出異常,會終止所有TestRunnable的運行,

並導致測試失敗.

Doc:

java.lang.Object

  extended bynet.sourceforge.groboutils.junit.v1.MultiThreadedTestRunner

public class MultiThreadedTestRunner

extends java.lang.Object

A framework which allows for an array of tests to be run asynchronously.

 TestCases should reference this class in a test method.

 

Update for July 9, 2003: now, you can also register TestRunner instances 

as monitors (request 771008); these run parallel with the standard 

TestRunner instances, but they only quit when all of the standard 

TestRunner instances end.

 

Fixed bugs 771000 and 771001: spawned threads are now Daemon threads, 

and all "wild threads" (threads that just won't stop) are Thread.stop()ed.

 

All these changes have made this class rather fragile, as there are many 

threaded timing issues to deal with. Expect future refactoring with backwards compatibility.

 

3.TestMonitorRunnable

表示監控線程,可以讓每一個TestRunnable對應一個TestMonitorRunnable,在TestMonitorRunnable中監控

TestRunnable.TestMonitorRunnable是TestRunnable的子類,提供了一些方便使用的方法.

TestMonitorRunnable使用示例參考:http://blog.csdn.net/wodestudy/article/details/17119741

 

附 TestMonitorRunnable 源碼:

public abstract class TestMonitorRunnable extends TestRunnable
{

    public TestMonitorRunnable()
    {
        super(true);
    }

    public abstract void runMonitor()
        throws Throwable;

    public void runTest()
        throws Throwable
    {
        for(; !isDone() && !Thread.interrupted(); yieldProcessing())
            runMonitor();

        runMonitor();
    }

    protected void yieldProcessing()
        throws InterruptedException
    {
        Thread.yield();
    }
}

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章