這是做為普通的測試案例,但是注意到這僅僅是一個測試案例,不包含其他任何邏輯,這也是 p-unit 追求的業(yè)務邏輯和測試運行環(huán)境分離的一個理念。同一個測試案例,用戶可以選擇不同的測試環(huán)境去運行,而不是綁定在某一個特定的測試軟件工具上,F(xiàn)在我們來看 p-unit 是如何運行這個測試案例的。你只需要在 main 函數(shù)中寫一行代碼來運行它:
清單 2. 單線程運行測試案例
public static void main(String[] args) {
new PUnitSoloRunner().run(SimpleTestClass.class);
}
清單 3. 單線程運行測試案例結果
[solo] Started running samples.SimpleTestClass
samples.SimpleTestClass
testA
testA() - [287.0ms]
testB() - [27.0ms]
testC() - [213.0ms]
total: 3, failures:0 (GREEN) - 2025.0ms
是否和想象中的一樣?下面我們來看如何多線程執(zhí)行這個測試案例;蛟S從上面的例子你已經(jīng)猜到了,在 main 函數(shù)還是只需一句代碼,只用把 PUnitSoloRunner 換成 PUnitConcurrentRunner 即可!
清單 4. 多線程運行測試案例
public static void main(String[] args) {
new PUnitConcurrentRunner().run(SimpleTestClass.class);
}
清單 5. 多線程運行測試案例結果
[concurrent] Started running samples.SimpleTestClass
samples.SimpleTestClass
testA
testA
testA
testA
testA
testA
testA
testA
testA
testA
testA() - [405.0ms]
testB() - [469.0ms]
testC() - [503.0ms]
total: 3, failures:0 (GREEN) - 1447.0ms
是否和想象中的一樣?默認情況 p-unit 啟動 10 個線程來執(zhí)行,要指定不同的線程數(shù),只需將線程數(shù)做為參數(shù)傳入 PUnitConcurrentRunner 即可。p-unit 甚至支持不同的測試案例有不同的線程數(shù),這要求測試案例實現(xiàn) p-unit 中定義的 Concurrent 接口,該接口的定義為:
清單 6. p-unit Concurrent 接口
public interface Concurrent {
public int concurrentCount();
}
該接口的意思,相信無需再多做解釋了,返回該測試案例需要的線程數(shù)。
參數(shù)化測試案例
性能測試,不同于單元測試,經(jīng)常要求測試不同數(shù)量級在同一個測試場景中的表現(xiàn),JUnit 是一款非常的單元測試工具,但沒覆蓋到這個方面。比如我們比較類庫 Foo1 的方法 bar() 和類庫 Foo2 的方法 bar() 哪個更符合自己的應用程序,我們需要測試該函數(shù)在應用程序可能的數(shù)量級的范圍內的表現(xiàn)。有經(jīng)驗的開發(fā)者知道經(jīng)常碰到在小數(shù)量級 A 更好大數(shù)量級 B 更好的局面,因此全面的測試對于代碼的性能理解非常重要,能幫助開發(fā)者做出正確的決定。p-unit 支持將參數(shù)傳給測試方法,測試案例需要實現(xiàn) p-unit 的 parameterizable 接口,該接口的主要方法是返回一組參數(shù)列表,這組列表的參數(shù)將會一一傳給測試方法。
清單 7. p-unit 參數(shù)化測試案例
public class ParamTestClass implements Parameterizable {
public static void main(String[] args) {
new PUnitSoloRunner().run(ParamTestClass.class);
}
public Parameter[] parameters() {
return new Parameter[] { new ParameterImpl(10), new ParameterImpl(20) };
}
public void testA(ParameterImpl param) {
SampleUtil.doSomething();
}
public void testB(ParameterImpl param) {
SampleUtil.doSomething();
}
public void testC(ParameterImpl param) {
SampleUtil.doSomething();
}
public void setUpAfterWatchers(Parameter param) throws Exception {
}
public void setUpBeforeWatchers(Parameter param) throws Exception {
}
public void tearDownAfterWatchers(Parameter param) throws Exception {
}
public void tearDownBeforeWatchers(Parameter param) throws Exception {
}
static class ParameterImpl implements Parameter {
private int _count;
ParameterImpl(int count) {
_count = count;
}
public int count() {
return _count;
}
public String toString() {
return String.valueOf(_count);
}
}
}