这是做为普通的测试案例,但是注意到这仅仅是一个测试案例,不包含其他任何逻辑,这也是 p-unit 追求的业务逻辑和测试运行环境分离的一个理念。同一个测试案例,用户可以选择不同的测试环境去运行,而不是绑定在某一个特定的测试软件工具上。现在我们来看 p-unit 是如何运行这个测试案例的。你只需要在 main 函数中写一行代码来运行它:
清单 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
是否和想象中的一样?下面我们来看如何多线程执行这个测试案例。或许从上面的例子你已经猜到了,在 main 函数还是只需一句代码,只用把 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 个线程来执行,要指定不同的线程数,只需将线程数做为参数传入 PUnitConcurrentRunner 即可。p-unit 甚至支持不同的测试案例有不同的线程数,这要求测试案例实现 p-unit 中定义的 Concurrent 接口,该接口的定义为:
清单 6. p-unit Concurrent 接口
public interface Concurrent {
public int concurrentCount();
}
该接口的意思,相信无需再多做解释了,返回该测试案例需要的线程数。
参数化测试案例
性能测试,不同于单元测试,经常要求测试不同数量级在同一个测试场景中的表现,JUnit 是一款非常的单元测试工具,但没覆盖到这个方面。比如我们比较类库 Foo1 的方法 bar() 和类库 Foo2 的方法 bar() 哪个更符合自己的应用程序,我们需要测试该函数在应用程序可能的数量级的范围内的表现。有经验的开发者知道经常碰到在小数量级 A 更好大数量级 B 更好的局面,因此全面的测试对于代码的性能理解非常重要,能帮助开发者做出正确的决定。p-unit 支持将参数传给测试方法,测试案例需要实现 p-unit 的 parameterizable 接口,该接口的主要方法是返回一组参数列表,这组列表的参数将会一一传给测试方法。
清单 7. p-unit 参数化测试案例
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);
}
}
}