IBM有奖问答 精美礼品等你来拿 详情请见:http://bbs.51testing.com/forum-231-1.html

扩展 JUnit 测试并行程序

上一篇 / 下一篇  2009-11-13 17:19:02 / 个人分类:单元测试

*PiPa]3gw2pD0  TDD(Test Driven Development)早已成为被广泛使用的敏捷实践。对于 Java 来说, JUnit 是备受开发人员喜爱的单元测试工具。它甚至还影响了其他语言的测试框架。这点,我们从繁多的 xUnit 框架就可以看出来。随着多核时代的到来,开发人员将需要进行越来越多的并行程序测试。得益于 JUnit 的可扩展性,我们可以使用 Annotation 让 JUnit 更好地支持并行测试。在本文中,我们将介绍一个对 JUnit 的扩展,从而使得我们可以方便的用并行的方式进行单元测试。

w6sQ]-ykBM/hd0

)YJP f,TGh3t0  测试并行程序与以往有什么不同 ?

Vv%L:H/b$YPEV0

!? z-e-?&st6lGZ0  随着多核的普及,并行程序的开发已经提上日程。相对串行程序而言,并行程序更有可能出错。一方面,并行程序的执行序列具有很强的随机性,线程交错执行的序列可能每次都不一样,而只要一个序列有问题,整个程序就是不正确的。另一方面,并行程序对大多数程序员来说,都是一个新的领域,经验相对较少,这是容易出错的另外一个因素。

#O5xELw!^M*T2H+U)E0

K)g#S V,L:f4Ue0  既然如此,我们就更需要仔细的测试我们的并行程序和组件了。目前已经有一些 JUnit 扩展可以创建多个线程,同时运行多个测试用例,从而加快测试用例集的执行速度,如 p-unit 。但对于测试并行程序和组件,这些功能并不能满足所有的需求。因为开发人员通常希望可以精确地控制多个线程之间的同步。51Testing软件测试网Nc6\3I!cX8Wx

51Testing软件测试网#@v_ S-h}B0c

  与测试顺序程序相同,我们希望能在测试并行操作之前,首先准备一些测试数据。然后,启动多个线程测试执行不同的操作。最后,等待所有线程结束之后,检验结果的正确性。在第二阶段中,多个线程能以任意的次序交错执行。结果的正确性检查应与线程的执行测序无关。51Testing软件测试网-}9D ^jgn

51Testing软件测试网E-V @7xjc

  标准 JUnit 只捕捉来自主线程的 Exception 。而其他线程中产生的 Exception 则会安静地被忽略掉,使得我们在子线程运行出错的情况下仍旧能得到“ Green Bar ”。这显然不是程序员喜欢的测试行为,我们希望测试结果能正确地反映所有线程的运行结果。51Testing软件测试网:i#wKK%A XPJs3i

Qy9@4jX#|0  这种用于并行程序的测试模式会在测试并行程序时会不断的重复。如果开发人员每次都需要重复创建这些框架,不仅繁琐,而且容易引入错误。通过使用以下介绍的简单扩展,可以使并行程序的测试变得和顺序程序一样简单。这种扩展并不影响 JUnit 的其他特性以及各种 IDE 的 JUnit 插件的使用。

z,Ck+UH,st051Testing软件测试网 KnEP FEFA

  下载并使用扩展框架

.nh/dIS051Testing软件测试网x]T]"r

  首先,我们给出一个使用新扩展进行并行测试的例子。51Testing软件测试网1{M vpS,i8~@"t

Dpj,ur$f0例 1. 使用 JUnit 扩展进行并行测试51Testing软件测试网)[p4V\o8U,A'I

51Testing软件测试网.Z E P'tC1yK*E

/** 
 * @author Zhi Gan 
 * 
 */ 
 @RunWith(Parallelized.class) 
 @ParallelSetting(threadNumber = { 1, 2, 4, 8 }) 
 public class TestThreaded { 
  Set<String> strSet; 

  @Before 
  public void setUp() { 
   strSet = new LockFreeSet(); 
  } 

  @Test 
  public void doNothing() { 

  } 
 
    @InitFor("testThread") 
  public void putSomeData(int size){ 
   strSet.add("putSomeData"); 
  } 

    @Threadedpublic void testThread(int rank, int size) { 
   // every thread adds element to set 
   strSet.add("abcde" + rank); 
  } 

    @CheckFor("testThread") 
  public void checkResult(int size) { 
   assertEquals(size+1, strSet.size()); 
  } 

  public static void main(String[] args) { 
   for (int i = 0; i < 10; i++) 
    JUnitCore.runClasses(TestThreaded.class); 
  } 
 }

[*z _2ay9D/k4L0

*I#|?chE6?0  如果我们在 Eclipse 中运行测试,那么测试完毕之后的 JUnit 视图如下所示:51Testing软件测试网4k\9y5k9ZSM!dp

51Testing软件测试网]#WkG T8Z P1C6{C!p

图 1. 并行测试的完成结果
Gj&S9GY6KD051Testing软件测试网 BD,\$Dv+cC

Sample figure containing an image

;Q5w`.I'q+u9?051Testing软件测试网Gc*l(@7g-IIUm


WC#l)i/M0O7UHo0

F-A o5W#o051Testing软件测试网!u-`qh&w)v Op

  接下来,我们模拟子线程在运行时抛出异常。

)m9O,tq~'G CQ0

5b$zK(v$p0例 2. 子线程运行时异常

.x#e\%E5X6[!V2G6M051Testing软件测试网C,ZCJ!qY;V

/** 
 * @author Zhi Gan 
 * 
 */ 
 @RunWith(Parallelized.class) 
 @ParallelSetting(threadNumber = { 1, 2, 4, 8 }) 
 public class TestThreaded { 
  Set<String> strSet; 

  @Before 
  public void setUp() { 
   strSet = new LockFreeSet(); 
  } 

  @Test 
  public void doNothing() { 

  } 
 
    @InitFor("testThread") 
  public void putSomeData(int size){ 
   strSet.add("putSomeData"); 
  } 

    @Threadedpublic void testThread(int rank, int size) { 
   // throw a runtime error in spawned thread 
   throw new RuntimeError(); 
  } 

    @CheckFor("testThread") 
  public void checkResult(int size) { 
   assertEquals(size+1, strSet.size()); 
  } 

  public static void main(String[] args) { 
   for (int i = 0; i < 10; i++) 
    JUnitCore.runClasses(TestThreaded.class); 
  } 
 }
51Testing软件测试网IWE-dD

51Testing软件测试网!|O_"a2hi

  如果我们在 Eclipse 中运行测试,那么测试完毕之后的 JUnit 视图如下所示:51Testing软件测试网e_lF4X

D0Gga [4d0图 2. 并行测试的完成结果51Testing软件测试网tZUeMt+K

Sample figure containing an image

9H/RS7I{'u y-J/h_Q051Testing软件测试网"Sut,U!R3{

  从上图可以看出,我们的并行测试用例通过了测试,并且它们在使用不同线程运行时都能正常的工作。而串行的测试方法 (doNothing) 的执行结果则完全和之前一样工作正常。也就是说,串行和并行测试可以在一个测试类中同时出现。

l\%^5Ap8{vk0

Z!l2j'L:?a8|6f&f8| }n;n0  Annotation 详细说明51Testing软件测试网.D\r ?$i4z7k

51Testing软件测试网C&v~ [ AKRb

表 1. 扩展的 annotation 说明

5\I4EzH#p3o0
名称参数使用对象备注
ParallelSettingthreadNum: 用于指定线程数目。通常我们希望能使用一个数组指定多个值,这样,我们可以了解程序是否在单线程,较少线程,以及大量线程的情况下是否工作正常。用于整个 TestCase 来指定测试所用的并行设置用于指定整个 TestCase 的并行设置
InitFor指定此方法服务的测试方法用于指定初始化方法所服务的并行测试方法 
Threaded无参数,或定义与 @Test 兼容的参数用于一个具有两个 int 类型的测试方法。测试过程中,测试框架将会线程序号以及线程总数通过方法的参数传递进来。这有点类似于 MPI 的约定。指明一个方法为并行测试方法,相当于 JUnit 原有的 @Test 注释
CheckFor一个字符串参数,用于指定需要被验证的并行测试方法。一个 Threaded 修饰的方法指明一个方法用于检测并行执行的结果 . 我们不能在 Threaded 方法中直接检查,因为其他线程的测试也许还没有结束。

5z4YbdF/^0  扩展 JUnit 的过程说明51Testing软件测试网I"~ B+| Q&h!rT

51Testing软件测试网1m b2R;v-lU:n(@2y)O

  归功于 JUnit 的灵活的内部架构,只要遵循 JUnit 的标准,我们就能够轻松的扩展 JUnit 的功能。而且遵循标准还意味着我们的扩展能无缝的利用社区对 JUnit 的广泛支持。例如,我们没有编写任何 Eclipse 插件,但是我们的测试结果能自然的在 Eclipse 中通过精心设计的 GUI 进行展现。

0N3^3U2^F/cD6Hq{$l0

2N,r\ p5O'`N0  言归正传,我们扩展 JUnit 的过程主要由以下过程组成:51Testing软件测试网 M!SrN{V7Z |A

51Testing软件测试网u0f+q1W:t4ub

  1. 生成 Annotation 的定义,包括:@Threaded, @InitFor, @Check, @ParallelSetting

6oc,obfHj051Testing软件测试网!ond'S\w:s*]

  2. 生成 TestClassRunner 的子类 Parallelized 并在其中实现运行自定义测试的逻辑51Testing软件测试网 HE)[w_1\~.T}!`

51Testing软件测试网@[v'_"n'b{u

  3. 生成 TestMethodRunner 的子类供 Parallelized 类使用51Testing软件测试网$oKh5\J*Z`P-d

'G/tmn:H};u0  在实现 ThreadedMethodRunner 时,我们最开始在类 ThreadedMethodRunner 使用了 Thread 类的 setDefaultUncaughtExceptionHandler 来捕获异常。然后将异常封装到主线程。而目前的版本则利用了 Executor 来运行多线程测试。由于 JDK 中的 Future 已经提供了类似的能力,所以我们不需要再关心异常的正确传递问题了。 JUnit 能准确的打印出并行测试中产生的异常信息,这也意味着我们可以使用 JUnit 提供的 Assert 功能了。

`1Bma4Cbj$F,R051Testing软件测试网 F_0|Sg+sY(z(x

  结论

IB0v4G)`&q051Testing软件测试网-q|l/qL

  随着多核平台逐渐成为主流,开发人员不可避免地需要开发和测试并行应用。本文通过使用 Annotation 扩展 JUnit,使其可以更方便地支持“准备数据——多线程运行——检查结果”三阶段的并行测试模式,减少开发人员手工创建线程和同步的繁琐工作。并且可以使 JUnit 支持从子线程中捕获测试错误,正确地在 Eclipse 等 IDE 中显示测试结果。51Testing软件测试网bfZ oN2PI+fxI*}

51Testing软件测试网o4tXs+^"EtS7V

作者信息:51Testing软件测试网J L _ ?T:E$H pB mtX

|3@~3D"c3o)B0甘 志 (ganzhi@cn.ibm.com), 高级软件工程师, IBM 中国软件开发中心51Testing软件测试网qt.pq-bgHJ
戴 晓君 (daixiaoj@cn.ibm.com), 软件工程师, IBM 中国软件开发中心51Testing软件测试网|q!I`_MM@
齐 尧 (qiyaoj@cn.ibm.com), 软件工程师, IBM 中国软件开发中心
)[G-Su;pc0罗 志达 (luozd@cn.ibm.com), 软件工程师, IBM 中国软件开发中心51Testing软件测试网)B(czc!r@ {7e\

P'B|s(Up"Jj0原文出处:

XJ7vd"VM1Bb0

d9bT&v~7pDYV0http://www.ibm.com/developerworks/cn/java/j-lo-junit-ext/51Testing软件测试网 a3Ewi;[

51Testing软件测试网$jw8R(?/i

点击免费获取RQM试用版安装光盘>>51Testing软件测试网 GMCVees_7g|

51Testing软件测试网?8atTUkq

更多精彩活动请点击:http://bbs.51testing.com/forum-231-1.html

,DI6{6UHJ0

TAG:

 

评分:0

我来说两句

Open Toolbar