单元级性能测试框架JunitPerf
上一篇 / 下一篇 2011-12-12 13:28:23 / 个人分类:软件测试工具
在应用程序的开发周期中,性能测试常被放到最后考虑,这并不是因为它不重要,而是因为存在这么多未知变量,很难有效地测试。由于种种原因,性能测试常被延迟到开发周期的后期。以我的经验,企业之所以在开发过程中不包含性能测试是因为,他们不知道对于正在进行开发的应用程序要期待什么。
7wC;m#u RK7R|}0v7z;y#YM#yP5bR:A0 发生下列两种情况之一时,性能测试就成为头等大事:1.生产中出现显而易见的性能问题;2.在产品交付之前,客户或潜在客户询问有关性能指数的问题。
Lc&KaZ)o^nn0q)}"xY&e6J'}+z0 2.用JUnitPerf进行测试
Z,dIlq h|"^%X-y w051Testing软件测试网5PoR3pT6]+B(G作为测试工程师执行性能测试时,首先想到的是LoadRunner、Jmeter等系统级性能测试工具,图表丰富,数据详细精确。但在在软件开发的早期阶段,采用此类方法不免有“牛刀杀鸡”之嫌,而且与我们目前的xUnit测试体系结合时还涉及到代码转换的技术处理工作,相对比较费时。前两天和晓峰交流时,网游测试团队也提到了CP方由于对LR这类系统级测试工具使用不惯,而不愿或不能执行性能测试的问题,那么JunitPerf作为Java语言的一个单元性能测试框架,对于Java开发工程师来说,应该是比较适合和易用的初级性能测试框架。51Testing软件测试网_7o,^ EN6T
51Testing软件测试网%O t7Eh5Iak%A在软件开发的早期阶段,使用JUnitPerf很容易确定基本的低端性能指数。JUnitPerf框架能够将测试快速地转化为简单的负载测试。可使用JUnitPerf创建两种测试类型:TimedTest和LoadTest。这两种类型都基于Decorator设计模式并利用JUnit的suite机制。51Testing软件测试网Ujp!B-dZM"pJ m Sk
51Testing软件测试网J/E8k$Ia7`C*TimedTest为测试样例创建一个(时间)上限——如果超过这个时间,那么测试失败。
0j!c#J%btu7V0(g z(s&R+z-t)g;Y8L0 *LoadTest和计时器一起运行,它通过运行所需的次数(时间间隔由配置的计时器控制),在一个特定的测试用例上创建一个人工负载。51Testing软件测试网0y'| cq7q{%Ae
51Testing软件测试网T&sBs'P,]"E3.TimedTest时限测试模式
$X.}Y&G Csp2S+{n;}0s Jp$X\'Sd T.U0 JUnitPerf TimedTest让您可以编写有相关时间限制的测试——如果超过了该限度,就认为测试是失败的(即便测试逻辑本身实际上是成功的)。在测试对于业务致关重要的方法时,时限测试相比其他测试来说,在确定和监控性能指数方面很有帮助。
-LKE}0d/wuJ0^;u#`,d4L6Lh9Mkk0 创建TimedTest首先要创建一个标准的JUnit测试。换言之,将对TestCase或其派生类进行扩展,并编写一个以test开头的方法,如清单1所示:51Testing软件测试网W t/O u(W2T8W
51Testing软件测试网6OW1u5t2_p4|51Testing软件测试网/FW!udKa#z
public class ExampleTestCase extends TestCase {51Testing软件测试网0dwrw(^V public ExampleTestCase(String name) { k9\`\v8L}E}0 super(name); M"bS*n:N1{0 }51Testing软件测试网hZ#i0o4lT$K protected void setUp() { A_-qY)N6f0 }51Testing软件测试网h LgJ9S1Ri protected void tearDown() { s1K:|3E3^*O0 }51Testing软件测试网3b`A1d&Zwm public void testOneSecondResponse() throws Exception { 8}GwHm#W9cD)g0 Thread.sleep(1000);51Testing软件测试网J$sZ f0[ IZ'sk }51Testing软件测试网1@*evNj%eA I i&V.NaPP0 public static Test suite() {51Testing软件测试网.TX7EXg$M5mjR return new TestSuite(ExampleTestCase.class);51Testing软件测试网6Pq+v_#_^F }51Testing软件测试网R(Y|R-QK;h9v @f FO w public static void main(String args[]) { e;v:N8uw^0 junit.textui.TestRunner.run(suite());51Testing软件测试网~ P~3`l }51Testing软件测试网 aSRMq,Yy } |
51Testing软件测试网-P;{&Z"ipP#I`N1e
h*^3N`KIaYCf\0 由于JUnitPerf是一个基于装饰器的框架,为了真正地驾驭它,必须提供一个suite()方法并将现有的测试装饰以TimedTest。TimedTest以Test和执行该测试的最大时间量作为参数。也可以选择传入一个boolean标志作为第三个参数(false),这将导致测试快速失败——意味着如果超过最大时间,JUnitPerf将立即迫使测试失败。否则,测试样例将完整运行,然后失败。区别很微妙:在一个失败的样例中,不带可选标志运行测试可以帮您了解运行总时间。传入false值却意味着得不到运行总时间。
#R5GK;k;Wrn051Testing软件测试网'TPz!wQu7F
清单2.为生成TimedTest而实现的suite方法
]5Fxby"fyha)Hc.B0
p+BS \(u0R6W4wet1] op+P.r0
public class ExampleTimedTest { A1S9SpER @*hn _"^0 public static final long toleranceInMillis = 100;51Testing软件测试网g^,z"ob1j public static Test suite() {51Testing软件测试网,c;aL9Hh %m}q/T6S eoU0 long maxElapsedTimeInMillis = 1000 + toleranceInMillis; CQ?m4pr#a0 Test testCase = new ExampleTestCase("testOneSecondResponse");51Testing软件测试网8B}C@;w S&[ Test timedTest = new TimedTest(testCase, maxElapsedTimeInMillis); /A-wV%gtv0 return timedTest; (^`*F EEw _0 } yDiS^#N0 public static void main(String args[]) { 9O3gHoj/RfP0 junit.textui.TestRunner.run(suite());51Testing软件测试网X/_4j/bAA0S-I } 4zs~H$fC0} |
#` ObV7T Z'S(r8X051Testing软件测试网1R/dvL N#RmW1Y
51Testing软件测试网sq5|4M2L}/U在运行测试用例时,我设置了1秒+允许误差时间为时间上限,如果执行总时间超过了这个时间,测试样例将失败。由于我并未传入可选的boolean参数,该测试将完整运行,而不管运行会持续多久。51Testing软件测试网n&N!U f'M%khbc!a
JE-|5F$N0 4.LoadTest负载测试模式
u[L4[0B{ q051Testing软件测试网Q c e~9PxU使用LoadTest,可以指定要模拟的用户(线程)数量,甚至为这些线程的启动提供计时机制。JUnitPerf提供两类Timer:ConstantTimer和RandomTimer。通过为LoadTest提供这两类计时器,可以更真实地模拟用户负载。如果没有Timer,所有线程都会同时启动。
*c lNsh051Testing软件测试网2kN/?e4d&P,G清单3是用ConstantTimer实现的含10个模拟用户的负载测试:
^)DW d,z(L"~051Testing软件测试网#o^mEOrg`1iqX4X E"Muz1J#Bb E0[4V^ W/L7y+g.|E0
public class ExampleLoadTest {51Testing软件测试网!T+A o
d6E]${+| public static final long toleranceInMillis = 100; #q$@3_3Y?0 public static Test suite() { ,F+[*i2Y+o8F:R0 TestSuite suite = new TestSuite(); wbqkk oH0 // Pn0S{$KI] y0 // Pick any example tests below. Hk"y,Aeee0 // D7X_Wh+?S%c0 suite.addTest(make1SecondResponse10UserLoad1SecondDelayIterationTest()); B:lTJ O0 return suite; .?.f D2PL0 }51Testing软件测试网@i2s.Ho^&YC protected static Test make1SecondResponse10UserLoad1SecondDelayIterationTest() {51Testing软件测试网hH"k"\I j*Z] int users = 10; o ~.GD'M$U0 int iterations = 10; 3Rus"Ued6YD.Y0 Timer timer = new ConstantTimer(1000); [%\ wWz d0 long maxElapsedTimeInMillis = 20000 + toleranceInMillis;51Testing软件测试网3uV$JD7n0a%HF Test testCase = new ExampleTestCase("testOneSecondResponse"); +}M)M XyQ&{0 Test loadTest = new LoadTest(testCase, users, iterations, timer); :e7a:yvd,Rv0 Test timedTest = new TimedTest(loadTest, maxElapsedTimeInMillis); JyLF\ d%Q*`0 return timedTest;51Testing软件测试网"ej'{)A"PL1U2acS'u }51Testing软件测试网4Qm| F G1L2P public static void main(String args[]) {51Testing软件测试网\+m[}Zs:tcb4W junit.textui.TestRunner.run(suite()); X|Fj$x)Vj!S0 } D {N"{&U$Z&v\nX0} |
10个用户并发执行测试,间隔时间设置为1秒,各运行10次,并且设置整个场景的最大时间为20秒加允许误差时间,否则整个测试场景将失败。51Testing软件测试网M2j,~C`yF
/JWEr$M0 5.其他51Testing软件测试网a~X$q
R+f6h
*O/}bojg"F0 JunitPerf是一个比较初级的性能测试框架,由JunitPerf装饰的测试都通过JUnit框架运行,所以就存在额外的消耗,特别是在利用fixture时。由于JUnit本身用一个setUp和一个tearDown()方法装饰所有测试样例,所以要在测试场景的整个上下文中考虑执行时间。相应地,我经常创建使用我想要的fixture逻辑的测试,但也会运行一个空白测试来确定性能指数基线。这是一个大致的估计,但它必须作为基线添加到任何想要的测试限制中。
8Pe[e/OL0AD gs7c&W u051Testing软件测试网N:d7W8p6t
D*\ l;qY1Uau;pG0
protected void setUp() { #T*`;{Mj[0 }51Testing软件测试网1gl.N.{CW protected void tearDown() {51Testing软件测试网^h0xE n C+i,G }51Testing软件测试网6O0n.v Ih public void testNothing{51Testing软件测试网1A-n4Q;rud@ //do nothing nf.ybD'}%l}0} |