上述代碼的執(zhí)行結(jié)果為:
清單 8. p-unit 參數(shù)化測(cè)試案例輸出
[solo] Started running samples.ParamTestClass
samples.ParamTestClass
testA(10) - [57936.0bytes,447.0ms]
testA(20) - [33128.0bytes,61.0ms]
testB(10) - [24832.0bytes,137.0ms]
testB(20) - [0.0bytes,63.0ms]
testC(10) - [83560.0bytes,468.0ms]
testC(20) - [16528.0bytes,47.0ms]
total: 6, failures:0 (GREEN) 1450.0ms
從上述結(jié)果看出,每個(gè)方法被執(zhí)行了 2 次,每次傳入不同的參數(shù)。多線程運(yùn)行參數(shù)化測(cè)試程序?相信讀者已經(jīng)明白怎么去實(shí)現(xiàn)了,只需將 PUnitSoloRunner 替換成 PUnitConcurrentRunner。
運(yùn)行環(huán)境測(cè)試案例
隨著 Java 開(kāi)源,出現(xiàn)了更多的 Java 運(yùn)行環(huán)境,除了 SUN 的參考實(shí)現(xiàn)外,BEA、IBM 均有自己的 Java 運(yùn)行環(huán)境,更有如 Apache Harmony 的開(kāi)源運(yùn)行環(huán)境(盡管現(xiàn)在 Apache Harmony 尚不能稱(chēng)為 Java 運(yùn)行環(huán)境)。運(yùn)行環(huán)境測(cè)試案例,為運(yùn)行環(huán)境開(kāi)發(fā)者以及選擇運(yùn)行環(huán)境,都能提供一定的幫助。比如說(shuō)下面的例子是測(cè)試 java.util.ArrayList 和 java.util.Vector 在兩個(gè)不同運(yùn)行環(huán)境的表現(xiàn)。測(cè)試案例寫(xiě)法和普通的測(cè)試案例完全一樣,我們只需告訴 p-unit 不同的運(yùn)行環(huán)境的 Java 路徑以及正確的 classpath,然后調(diào)用 runVMs 函數(shù)即可:
清單 9. p-unit 運(yùn)行環(huán)境測(cè)試案例
public static void main(String[] args) {
PUnitSoloRunner runner = new PUnitSoloRunner();
runner.addPUnitEventListener(new OverviewReporter(new ImageRender()));
runner.runVMs(ListTestClass.class, new VM[] { VMConfig.HARMONY, VMConfig.SUN });
}
public class VMConfig {
private static String CLASSPATH = " -cp correct_classpath_including_all_jars_and_path";
private static String HARMONY_PATH = "harmony_path\bin\java" + CLASSPATH;
private static String SUN_PATH = "sun_path\bin\java" + CLASSPATH;
public static VM HARMONY = new VM(HARMONY_PATH, "HARMONY");
public static VM SUN = new VM(SUN_PATH, "SUN");
}
public class ListTestClass {
private static final int LIST_COUNT = 100000;
private static Object element = new Object();
private Random indexGenerator = new Random();;
public void testInsertArrayList() {
ArrayList arrayList = new ArrayList(LIST_COUNT);
insertSequence(arrayList);
insertRandom(arrayList);
}
public void testInsertVector() {
Vector vector = new Vector(LIST_COUNT);
insertSequence(vector);
insertRandom(vector);
}
public void insertSequence(List list) {
for (int i = 0; i < LIST_COUNT; ++i) {
list.add(element);
}
}
public void insertRandom(List list) {
for (int i = 0; i < LIST_COUNT; ++i) {
list.add(indexGenerator .nextInt(LIST_COUNT),element);
}
}
}
上述代碼的運(yùn)行結(jié)果如下:
圖 1. 運(yùn)行環(huán)境測(cè)試案例結(jié)果
從上圖中可以很直觀的看出,筆者使用的 HARMONY 版本在該測(cè)試案例中速度更快(左圖),但內(nèi)存消耗更多(右圖)。下一節(jié)將講述如何輸出報(bào)表,但或許你已經(jīng)注意到了,代碼非常簡(jiǎn)單。
從上面的實(shí)例中我們已經(jīng)看到 p-unit 的輸出結(jié)果的兩種形式,控制臺(tái)和報(bào)表圖片。默認(rèn)情況下,p-unit 將輸出到控制臺(tái)。p-unit 采用事件機(jī)制,在運(yùn)行器的每個(gè)節(jié)點(diǎn)都會(huì)提供通知事件。所有的輸出都是通過(guò)注冊(cè)事件響應(yīng)器來(lái)實(shí)現(xiàn)的。這也表明了結(jié)果輸出和運(yùn)行器完全隔離,用戶也可以定制自己的報(bào)表。p-unit 有 4 種內(nèi)建輸出,分別為控制臺(tái)、文件、圖片報(bào)表以及 PDF 報(bào)表。上一節(jié)的例子中我們已經(jīng)看到圖片報(bào)表,其代碼為:
清單 10. 添加 p-unit 總體圖片報(bào)表
runner.addPUnitEventListener(new OverviewReporter(new ImageRender()));
p-unit 內(nèi)建的報(bào)表有分三種不同的粒度:總體級(jí)別(OverviewReporter),TestSutie 級(jí)別(TestSuiteReporter),以及測(cè)試案例類(lèi)級(jí)別(TestClassReporter)。這三種級(jí)別都可以輸出圖片格式或是 PDF 格式,因此,總共有六種類(lèi)型的輸出。上述的代碼是輸出總體級(jí)別的圖片。由于事件監(jiān)聽(tīng)器是互相獨(dú)立的,因此你可以既選擇輸出圖片又選擇輸出 PDF 文件,只需再添加事件監(jiān)聽(tīng)器即可:
清單 11. 添加多個(gè) p-unit 事件監(jiān)聽(tīng)器
runner.addPUnitEventListener(new OverviewReporter(new ImageRender()));
runner.addPUnitEventListener(new OverviewReporter(new PDFRender()));
總結(jié)
至此,你是否基本理解了 p-unit 的概念呢?簡(jiǎn)單,易用,關(guān)注多線程,關(guān)注性能,這是 p-unit。此外 p-unit 還有很多很好的小特性,如 Alphabetical 接口來(lái)保證執(zhí)行測(cè)試函數(shù)的先后順序等。使用 p-unit,讓你的代碼更健壯!