单元级性能测试框架JunitPerf

上一篇 / 下一篇  2011-12-12 13:28:23 / 个人分类:软件测试工具

1.前言51Testing软件测试网Zc9wu1Vs S4c

  在应用程序的开发周期中,性能测试常被放到最后考虑,这并不是因为它不重要,而是因为存在这么多未知变量,很难有效地测试。由于种种原因,性能测试常被延迟到开发周期的后期。以我的经验企业之所以在开发过程中不包含性能测试是因为,他们不知道对于正在进行开发的应用程序要期待什么。

7wC;m#uR K7R |}0

v7z;y#YM#y P5bR:A0  发生下列两种情况之一时,性能测试就成为头等大事:1.生产中出现显而易见的性能问题;2.在产品交付之前,客户或潜在客户询问有关性能指数的问题。

Lc&KaZ)o^nn0

q)}"xY&e6J'}+z0  2.用JUnitPerf进行测试

Z,dIlq h|"^%X-y w051Testing软件测试网5PoR3pT6]+B(G

  作为测试工程师执行性能测试时,首先想到的是LoadRunnerJmeter系统级性能测试工具,图表丰富,数据详细精确。但在在软件开发的早期阶段,采用此类方法不免有“牛刀杀鸡”之嫌,而且与我们目前的xUnit测试体系结合时还涉及到代码转换的技术处理工作,相对比较费时。前两天和晓峰交流时,网游测试团队也提到了CP方由于对LR这类系统级测试工具使用不惯,而不愿或不能执行性能测试的问题,那么JunitPerf作为Java语言的一个单元性能测试框架,对于Java开发工程师来说,应该是比较适合和易用的初级性能测试框架。51Testing软件测试网_7o,^ EN6T

51Testing软件测试网%Ot7Eh5Iak%A

  在软件开发的早期阶段,使用JUnitPerf很容易确定基本的低端性能指数。JUnitPerf框架能够将测试快速地转化为简单的负载测试。可使用JUnitPerf创建两种测试类型:TimedTest和LoadTest。这两种类型都基于Decorator设计模式并利用JUnit的suite机制。51Testing软件测试网Ujp!B-dZM"pJmSk

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,]"E

  3.TimedTest时限测试模式

$X.}Y&G Csp2S+{n;}0

s Jp$X\'Sd T.U0  JUnitPerf TimedTest让您可以编写有相关时间限制的测试——如果超过了该限度,就认为测试是失败的(即便测试逻辑本身实际上是成功的)。在测试对于业务致关重要的方法时,时限测试相比其他测试来说,在确定和监控性能指数方面很有帮助。

-L K E}0d/wuJ0

^;u#`,d4L6Lh9Mkk0  创建TimedTest首先要创建一个标准的JUnit测试。换言之,将对TestCase或其派生类进行扩展,并编写一个以test开头的方法,如清单1所示:51Testing软件测试网Wt/Ou(W2T8W

51Testing软件测试网6OW1u5t2_p4|

51Testing软件测试网/FW!u dK a#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_-q Y)N6f0 }51Testing软件测试网hLgJ9S1Ri
 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@*evN j%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 FOw
 public static void main(String args[]) {
e;v:N8uw^0  junit.textui.TestRunner.run(suite());51Testing软件测试网~ P~3`l
 }51Testing软件测试网 aSRMq,Yy
}
51Testing软件测试网XB'b7T;r];Zz5q)}g/X

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方法

3gJ4e9Jv;a [L(iB(C0

]5Fxby"fyh a)Hc.B0

p+BS \(u0

R6W4we t1] op+P.r0

public class ExampleTimedTest {
A1S9SpER @*hn _"^0 public static final long toleranceInMillis = 100;51Testing软件测试网g^,z"o b1j
 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[]) {
9O3gH oj/RfP0  junit.textui.TestRunner.run(suite());51Testing软件测试网X/_4j/bAA0S-I
 }
4zs~H$fC0}
51Testing软件测试网[MWJ7N-|.|8Pb`(iED

#` ObV7T Z'S(r8X051Testing软件测试网1R/dvL N#RmW1Y

51Testing软件测试网s q5|4M2L}/U

  在运行测试用例时,我设置了1秒+允许误差时间为时间上限,如果执行总时间超过了这个时间,测试样例将失败。由于我并未传入可选的boolean参数,该测试将完整运行,而不管运行会持续多久。51Testing软件测试网n&N!U f'M%khb c!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个模拟用户的负载测试:

^)D W d,z(L"~051Testing软件测试网#o^mE Org`1i

q X4X 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;
.?.fD2P L0 }51Testing软件测试网@i2s.Ho^&YC
 protected static Test make1SecondResponse10UserLoad1SecondDelayIterationTest() {51Testing软件测试网hH"k"\Ij*Z]
  int users = 10;
o~.GD'M$U0  int iterations = 10;
3Rus"Ued6YD.Y0  Timer timer = new ConstantTimer(1000);
[%\ wWzd0  long maxElapsedTimeInMillis = 20000 + toleranceInMillis;51Testing软件测试网3uV$JD7n0a%H F
  Test testCase = new ExampleTestCase("testOneSecondResponse");
+}M)MXy Q&{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| FG1L2P
 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}

TF+BR XHP:s T5~051Testing软件测试网@\2~'j]U&M

+^VpI,MJ051Testing软件测试网v&u{t W]:nA0Y

  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/OL0

AD 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}

i9[mfx0

+o]S,SM [r8^0

]!b,Z.qP O AF@ e]-^051Testing软件测试网8Pek Pc}$o3k/n

  特别还需要注意的,如果要采用Junit4.x中采用annotation新特性编写的测试用例来执行性能,还需要对JunitPerf增加一点改造,如下51Testing软件测试网#W h*B{ z.w8z^r `r7`\

JG8] Y{051Testing软件测试网S HJ iN

;I5e9c j}*v-w"n0

class JUnit4TestFactory extends TestFactory {  
&Lg(_BZ!b[Vj)b0 static class DummyTestCase extends TestCase {     51Testing软件测试网I*@,\(jKw/i_F
  public void test() {51Testing软件测试网e/Rz#WT
  }51Testing软件测试网 ylP^M0s*O5x
  }51Testing软件测试网,?1L6R#@ Q!P
 private Class<?> junit4TestClass;51Testing软件测试网]0E t yYI.{
 public JUnit4TestFactory(Class<?> testClass) {51Testing软件测试网"l*\1Q OIe~.NC*s{!c
  super(DummyTestCase.class);
-o Rdn6d*GHg#Wx0  this.junit4TestClass = testClass;51Testing软件测试网(dv$u-V YSQ
  }
4T8X2M J(h0 @Override  51Testing软件测试网6^y&\X;|v o#CT#l
 protected TestSuite makeTestSuite() {51Testing软件测试网 RG7N4l'uu(c(O;pN
  JUnit4TestAdapter unit4TestAdapter = new JUnit4TestAdapter(this.junit4TestClass);51Testing软件测试网$n }!p|`\)y,[ux)j
  TestSuite testSuite = new TestSuite("JUnit4TestFactory");51Testing软件测试网S-b k:i ch9|
  testSuite.addTest(unit4TestAdapter);51Testing软件测试网H:ZLs7y }
  return testSuite;51Testing软件测试网{N7L(av @b
  }51Testing软件测试网;X~LC ?p]
 }

]L$Jx1zH051Testing软件测试网!Hb.{7T-\Iy5Sg

2wf.q6A4l5z`051Testing软件测试网W_Kiy*ZK2X

  Junit4.x测试脚本

6w3v%|6i8NtS051Testing软件测试网hT].lzm?O.rw)x7F

51Testing软件测试网? MjqAW6]*Z$V+F

&h(G1p})N;m?/T0

public class ExampleTestCase extends TestCase {
#@n8}9}7t/L0@Before51Testing软件测试网$B$\|TQ:F_
 protected void setUp() {51Testing软件测试网.wLh Wy'E
 }51Testing软件测试网"KF"Kv6V+o
@After
R\KGM0 protected void tearDown() {
"|f2x)r }f~2}0 }51Testing软件测试网Y/v&l6OX
@Test51Testing软件测试网YZ;w!B ieM5J
 public void testOneSecondResponse() throws Exception {
],pa N5W-[n0  Thread.sleep(1000);
#Y,TG+c#D1B"lv F0 }

'rD^@!Z0

/nZ-pHOl:@T0

beVI oChl4d0

j/?4}[ invk#}0  采用JunitPerf执行性能测试51Testing软件测试网7O6U/bL,Z XL ?/[n:vB!D2L

51Testing软件测试网-m$L5Zn'PTO%\

51Testing软件测试网l;a2oWH0Ary1{@

hz Z`-V'M0

public class ExampleTimedTest2 {51Testing软件测试网&pP5Lc8n:b8Ou
public static final long toleranceInMillis = 100;
GlLL0N:^0    public static Test suite() {51Testing软件测试网A$E*cM |7bX
     long maxElapsedTimeInMillis = 1000+toleranceInMillis;51Testing软件测试网^6v W.lx
     JUnit4TestFactory mytestfactory = new JUnit4TestFactory(ExampleTestCase.class);
jEc!ps0     Test testCase = mytestfactory.makeTestSuite();51Testing软件测试网z6dX!AO s9o#bhF
     Test timedTest = new TimedTest(testCase, maxElapsedTimeInMillis);51Testing软件测试网;T#v P ~ L~R+pu2f
     return timedTest;
K5]+S`'_.cte0     }
t l$nK5Q.KX0 public static void main(String args[]) {51Testing软件测试网vj+o5}U.kgQ9A(^)Iw
  junit.textui.TestRunner.run(suite());
"['jc'`'r M&Lp#]0 }51Testing软件测试网9l7q BeP5Fw:y{
}

q.R(C:]2|[bL}'~I051Testing软件测试网9}7sf? BRf|

51Testing软件测试网@`2l*xJ"@C8k3^

51Testing软件测试网&\$l-N,m"B"BR

  试试吧!51Testing软件测试网 T"{/[B;C.T7` I

^|.T0Q)}.Q9H~O0  用JUnitPerf进行性能测试无疑是一门严格的科学,但在开发生命周期的早期,这是确定和监控应用程序代码的低端性能的极佳方式。另外,由于它是一个基于装饰器的JUnit扩展框架,所以可以很容易地用JUnitPerf装饰现有的JUnit测试。

-J}4EoH.r:i.E051Testing软件测试网7U2\r,\9`%b

  想想您已经花了这么多时间来担心应用程序在负载下会怎样执行。用JUnitPerf进行性能测试可以为您减少担忧并节省时间,同时也确保了应用程序代码的质量

$R&i)UHOyt"y9Y!I_8x0

TAG:

 

评分:0

我来说两句

Open Toolbar