追求代码质量: 用 JUnitPerf 进行性能测试-2

上一篇 / 下一篇  2011-12-15 09:00:20 / 个人分类:软件测试工具

测试通常在 JUnit 框架中运行 —— 现有的 Ant 任务、Eclipse 运行器等等,会像运行任何其他 JUnit 测试一样运行这个测试。惟一的不同是,该测试将发生在计时器的上下文中。51Testing软件测试网"WyH5LWY0{0oz
51Testing软件测试网BLW2F#d FX
过度的负载测试51Testing软件测试网'U^7o j5fej

k|.Js8[5^0与在测试场景中验证一个方法(或系列方法)的时间限制正好相反,JUnitPerf 也方便了负载测试。正如在 TimedTest 中一样,JUnitPerf 的 LoadTest 也像装饰器一样运行,它通过将 JUnit Test 和额外的线程信息绑定起来,从而模拟负载。
w"Jv9QV.O%x Y^^3n051Testing软件测试网AZr&BE'N^2`8}
使用 LoadTest,可以指定要模拟的用户(线程)数量,甚至为这些线程的启动提供计时机制。JUnitPerf 提供两类 Timer:ConstantTimer 和 RandomTimer。通过为 LoadTest 提供这两类计时器,可以更真实地模拟用户负载。如果没有 Timer,所有线程都会同时启动。
l(P#}U VU2l| A051Testing软件测试网4F%q&jMQ2H[l1H`:K9b
清单 3 是用 ConstantTimer 实现的含 10 个模拟用户的负载测试:51Testing软件测试网$q"D-i+H N7]K?

R5~/g^I/B7|#U/T0
A} Nv.@4a K,uD0清单 3. 为生成负载测试而实现的 suite 方法
C*st?d'M)z3H0public static Test suite() {
SW%R:{[Xd0int users = 10;
3pAtwtxM0Timer timer = new ConstantTimer(100);51Testing软件测试网NI bP1d8y%_x Hs;X
return new LoadTest(51Testing软件测试网yX8JJ5~V9~
new WidgetDAOImplTest("testCreate"),51Testing软件测试网"sa#vrr z
users, timer);51Testing软件测试网 `KcJ"D9g'r7~
}
|Dc-Wm/^051Testing软件测试网dT/OtK:JtB1j

)u}Yt;J j x0
5N"JP.O&YrI-e0请注意,testCreate() 方法运行 10 次,每个线程间隔 100 毫秒启动。未设定时间限制 —— 这些方法完整运行,如果其中任何的方法执行失败,JUnit 会相应地报告失败。51Testing软件测试网r;@y#rA

P*Y,Y.CF"KrE A0用样式进行装饰
"I@,Cy:N&d9PX051Testing软件测试网V7q K5rE
装饰器并不局限于单个的装饰物。例如,在 Java™ I/O 中,可以为 FileInputStream 装饰上一个带 BufferedReader 的 InputStreamReader(只要记住:BufferedReader in = new BufferedReader(new InputStreamReader(new FileInputStream("infilename"), "UTF8")))。
_7D+S0p2^$V.l[u051Testing软件测试网m D G bpBZ
装饰可以有多个层次,JUnitPerf 的 TimedTest 和 LoadTest 也是一样。当这两个类彼此装饰时,将导致一些强制的测试场景,例如像这样的场景:在一项业务中放置了负载并应用了时间限制。或者,我们可以仅仅将之前的两个测试场景以如下方式结合起来:51Testing软件测试网7z ~*S v Z9|

T(G5by A2E0在 testCreate() 方法中放置一项负载。51Testing软件测试网0Jc+h&_1k E4wp
规定每个线程必须在该时间限制内结束。51Testing软件测试网 k'@[Z'N?-rb(Vd_
我通过为一个标准 Test 装饰上 LoadTest(由 TimedTest 装饰)应用了上述规范,清单 4 显示了其结果。51Testing软件测试网YM$I MeM$_
51Testing软件测试网0[#I&h+[t ?1p}

^(u'\rdK0清单 4. 经装饰的负载和时限测试51Testing软件测试网(A5hvYd3Q
public static Test suite() {
6t#K7eU)XB e;x']9S0int users = 10;
:X9P];xj$@@0Timer timer = new ConstantTimer(100);
"C#E2{o+P-Ot0long maxElapsedTime = 2000;51Testing软件测试网I0S&__anxA
return new TimedTest(new LoadTest(
_XOj+u4_6e/K0new WidgetDAOImplTest("testCreate"), users, timer),51Testing软件测试网f iO,K(|$eq!|)n
maxElapsedTime);
@$dY`wR0}
Md8D/J}0正如您所看到的那样,testCreate() 方法运行 10 次(每隔 100 毫秒启动一个线程),且每个线程必须在 2 秒内完成,否则整个测试场景将失败。
nG+b8v(i`h051Testing软件测试网'Uf}pc1\F&G
使用注意
]z!?h^Xs0H051Testing软件测试网JR ik#x
尽管 JUnitPerf 是一个性能测试框架,但也要先大致估计一下测试要设定的性能指数。这是由于所有由 JUnitPerf 装饰的测试都通过 JUnit 框架运行,所以就存在额外的消耗,特别是在利用 fixture 时。由于 JUnit 本身用一个 setUp 和一个 tearDown() 方法装饰所有测试样例,所以要在测试场景的整个上下文中考虑执行时间。
8u,a/Hz3k(N0
3@-I PM w0相应地,我经常创建使用我想要的 fixture 逻辑的测试,但也会运行一个空白测试来确定性能指数基线。这是一个大致的估计,但它必须作为基线添加到任何想要的测试限制中。51Testing软件测试网/MXEL!S
51Testing软件测试网!Oa%`;Oi
例如,如果运行一个由 fixture 逻辑(使用 DbUnit)装饰的空白测试用时 2.5 秒,那么您想要的所有测试限制都应将这一额外时间考虑在内 —— 这可以从清单 5 中的基准测试中看到:51Testing软件测试网 s NnW@$ux-S\aU
51Testing软件测试网D2G2|B'x f e{D0F

清单 5. JUnitPerf 基准测试51Testing软件测试网$e9X2iLQ8`^L
public class DBUnitSetUpBenchmarkTest extends DatabaseTestCase {
EJ2j"I&q5zd1h0private WidgetDAO dao = null;51Testing软件测试网]e}$[:L V
51Testing软件测试网q ZP.j:~9e
public void testNothing(){
l-k)W ~y N!t0//should be about 2.5 seconds
0Q^4O(IL`C0}51Testing软件测试网$Pd1} I7ve O7M
51Testing软件测试网d b P\Jm)i9G V M*NJR+U
protected IDatabaseConnection getConnection() throws Exception {51Testing软件测试网A-o-udf
Class driverClass = Class.forName("org.hsqldb.jdbcDriver");
3R6_9O,`)dI(D'_0Connection jdbcConnection =51Testing软件测试网W\NN#]6E5Yf
DriverManager.getConnection(
X7^a@SG.M'Cy{0"jdbc:hsqldb:hsql://127.0.0.1", "sa", "");51Testing软件测试网*F WWn,D6Y u
return new DatabaseConnection(jdbcConnection);
sMY,sq:Cl&m0}
1S4q1c0w6t9o.T;M||h0
#?2{8Q6^q|0_ i:EN0protected IDataSet getDataSet() throws Exception {51Testing软件测试网V4JlMF0t2E
return new FlatXmlDataSet(new File("test/conf/seed.xml"));
M?@c1T"CW2_?b0}51Testing软件测试网$omCw#Nl#B8n
51Testing软件测试网)cE)_:x [ D
protected void setUp() throws Exception {
zVg1`%gK[HW0super.setUp();51Testing软件测试网mP;F M#g'l*b
final ApplicationContext context =51Testing软件测试网SSHo LEqEP4W
new ClassPathXmlApplicationContext("spring-config.xml");
0g ^+t"t_]&H0this.dao = (WidgetDAO) context.getBean("widgetDAO");
3w5k&vE!]0}51Testing软件测试网.V`4B%w7c/rG&R8ZE
}
NIzn6v9{K"_%i2lR051Testing软件测试网6W9Z1hV:CD+k z
51Testing软件测试网1y V.XG[ P2M]_

$BZVXQ0请注意,清单 5 的测试样例 testNothing() 什么都没做。其惟一的目的是确定运行 setUp() 方法(当然,该方法也通过 DbUnit 设置了一个数据库)的总时间。51Testing软件测试网5A.J?[hM

C*wO/Hg r0也请记住,测试时间将依赖于机器的配置而变化,同时也依赖于在执行 JUnitPerf 测试时运行的东西而变化。我经常发现,将 JUnitPerf 测试放到它们自己的分类中有助于将它们同标准测试隔离开。这意味着,在运行一个测试时不必每次都运行 JUnitPerf 测试,例如在一个 CI 环境中签入代码。我也会创建特定的 Ant 任务,从而只在精心策划的将性能测试考虑在内的场景或环境中运行这些测试。51Testing软件测试网6q OL#D(\Pp

ONJ ixN6z} u(r0试试吧!
!WUQ T7O$v P;C051Testing软件测试网D8m&|(Z0n
用 JUnitPerf 进行性能测试无疑是一门严格的科学,但在开发生命周期的早期,这是确定和监控应用程序代码的低端性能的极佳方式。另外,由于它是一个基于装饰器的 JUnit 扩展框架,所以可以很容易地用 JUnitPerf 装饰现有的 JUnit 测试。51Testing软件测试网W Wu1wHj n/RS

(U7Og5`?3f6m7O0想想您已经花了这么多时间来担心应用程序在负载下会怎样执行。用 JUnitPerf 进行性能测试可以为您减少担忧并节省时间,同时也确保了应用程序代码的质量。
51Testing软件测试网b6YA R/UuT9z([


TAG:

 

评分:0

我来说两句

Open Toolbar