后,還有個(gè)org.jboss.jrunit.TestDriver類,用于表示客戶端和服務(wù)器端測(cè)試的“驅(qū)動(dòng)”。這個(gè)類可以產(chǎn)生新的test harness,把客戶端和服務(wù)器端的test case放在里面跑。這個(gè)測(cè)試驅(qū)動(dòng)可以通過一個(gè)JGroup消息總線與那些test harness進(jìn)行通訊,從而控制服務(wù)器和所有客戶端的test case,并從它們那里獲得測(cè)試結(jié)果
邏輯上,運(yùn)行一個(gè)由test runner控制的測(cè)試的順序如下:
(The logical order of a test run as controlled by the test runner is: )
(譯注:這個(gè)test runner可能是指剛才所說的driver)
1.為每個(gè)客戶端和服務(wù)器端test case生成一個(gè)新的test harness
2.等待確認(rèn),直至所以test harness創(chuàng)建完畢,它們各自的消息總線也已經(jīng)啟動(dòng)
3.一旦收到確認(rèn),會(huì)等待服務(wù)器端的test case啟動(dòng)(比如,調(diào)用服務(wù)器test case的setUp方法)。否則,假如沒有收到確認(rèn),殺死所以進(jìn)程,返回出錯(cuò)信息給JUnit。(譯注:可見jrunit只是junit的一個(gè)擴(kuò)展,底層還是依賴于junit的實(shí)現(xiàn),比如錯(cuò)誤提示)
4.確認(rèn)服務(wù)器端啟動(dòng)完畢后,通知所有的test case(客戶端和服務(wù)器的)開始運(yùn)行。否則(如果沒有確認(rèn)信息),對(duì)所有test harness發(fā)送退出信息。
5.等待客戶端test case的結(jié)果
6.一旦收到全部客戶端返回的結(jié)果,通知服務(wù)器進(jìn)行tear down(例如,調(diào)用服務(wù)器test case的teardown方法)。否則,殺死所以進(jìn)程返回出錯(cuò)信息給JUnit
7.等待服務(wù)器端的測(cè)試結(jié)果(當(dāng)然服務(wù)器test case要有test方法)
8.處理所有測(cè)試結(jié)果,提交給JUnit TestResult類,測(cè)試結(jié)果會(huì)以普通Junit測(cè)試報(bào)告的方式呈現(xiàn)出來。
9.等待服務(wù)器關(guān)閉的信息,表明服務(wù)器已經(jīng)成功地關(guān)閉并清理完資源
10.關(guān)閉消息總線和根測(cè)試(root test run),返回至Junit的執(zhí)行線程中。
對(duì)于test driver,用戶需要進(jìn)行編碼的地方是實(shí)現(xiàn)一個(gè)繼承自org.jboss.jrunit.TestDriver的抽象類,并實(shí)現(xiàn)其中的declareTestClasses()方法。在這個(gè)方法內(nèi)部調(diào)用TestDriver類的addTestClasses方法,并且指定客戶端test case類、客戶端的并發(fā)數(shù)量以及服務(wù)器端test case類
基準(zhǔn)修飾符(Benchmark Decorator)
JRunit使用基準(zhǔn)修飾符來提供除了普通Junit測(cè)試結(jié)果外的一些數(shù)據(jù),稱為基準(zhǔn)結(jié)果
org.jboss.jrunit.decorators.ThreadLocalDecorator(以及其他可以接收線程個(gè)數(shù)和循環(huán)次數(shù)(等參數(shù))的修飾符)——指定多少個(gè)線程數(shù),會(huì)有多少個(gè)執(zhí)行同一個(gè)測(cè)試的線程被創(chuàng)建。指定多少次循環(huán),會(huì)在每個(gè)測(cè)試實(shí)例中,對(duì)每個(gè)測(cè)試方法循環(huán)那么多次。比如,如果指定3個(gè)線程、10次循環(huán),那么將會(huì)有三個(gè)線程執(zhí)行該測(cè)試用例(也即創(chuàng)建了三個(gè)測(cè)試實(shí)例),每個(gè)測(cè)試實(shí)例中,會(huì)將里面的所以test方法執(zhí)行10遍。下面是一個(gè)相關(guān)的例子:
public class SimpleThreadLoopCounter extends TestCase
{
private static int staticCounter = 0;
private static int staticMethodCounter = 0;
private int localCounter = 0;
public static Test suite()
{
return new ThreadLocalDecorator(SimpleThreadLoopCounter.class, 3, 10, 0, true, true);
}
public SimpleThreadLoopCounter()
{
staticCounter++;
}
public void testCounter() throws Exception
{
System.out.println("staticCounter = " + staticCounter);
System.out.println("staticMethodcounter = " + ++staticMethodCounter);
System.out.println("localCounter = " + ++localCounter);
}
}
運(yùn)行這個(gè)例子,后的輸出會(huì)是:
staticCounter = 3 staticMethodcounter = 30 localCounter = 10
有個(gè)問題是關(guān)于junit如何處理多個(gè)test方法(譯注:具體方式在開頭已經(jīng)有所說明)。對(duì)于每個(gè)test case中的每個(gè)test方法,junit都會(huì)創(chuàng)建一個(gè)新的測(cè)試實(shí)例來運(yùn)行這個(gè)方法。為了說明這一點(diǎn),我們復(fù)制上面代碼的testCounter方法(把復(fù)制后的改名為testCounter2),那么在輸出結(jié)果中后一行變?yōu)椋?br />
staticCounter = 6 staticMethodcounter = 60 localCounter = 10
(譯注:指定了三個(gè)線程,junit又為每個(gè)測(cè)試類創(chuàng)建兩個(gè)實(shí)例,所以總共3×2個(gè),但是對(duì)于每一個(gè),它的localCounter 還是10,即執(zhí)行了10次循環(huán))
JRUnit和修飾符的注意事項(xiàng):如果numberOfThreads大于1,那ServerTestHarness不會(huì)運(yùn)行。但是numberOfThreads可以拿來模擬同一時(shí)刻并發(fā)的客戶端數(shù)量,從這個(gè)意義上來說,我認(rèn)為這不算是個(gè)大問題。如果要用ServerTestHarness來這么做,事實(shí)上也的確可以產(chǎn)生多個(gè)客戶端。即時(shí)這些客戶端不是在一個(gè)進(jìn)程中并發(fā)運(yùn)行,起碼也是在各個(gè)單獨(dú)的進(jìn)程中并發(fā)。而能夠設(shè)定循環(huán)變量也是很有必要的,雖然這樣會(huì)讓客戶端額外地調(diào)用服務(wù)器一段時(shí)間(或者反復(fù)調(diào)用)。因此,如果進(jìn)行遠(yuǎn)程測(cè)試并且要用ThreadLocalDecorator獲取基準(zhǔn)數(shù)據(jù)的話,你可以使用下面這個(gè)ThreadLocalDecorator的構(gòu)造器,它的線程數(shù)是默認(rèn)為1的
public ThreadLocalDecorator(Class testClazz, int loops)