技术开发 频道

扩展JUnit测试并行程序

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

  例 2. 子线程运行时异常

  /**

  * @author Zhi Gan

  *

  */

  @RunWith(Parallelized.class)

  @ParallelSetting(threadNumber = { 1, 2, 4, 8 })

  public class TestThreaded {

  Set 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);

  }

  }

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

  图 2. 并行测试的完成结果

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

  Annotation详细说明

  表 1. 扩展的 annotation 说明

  ParallelSetting threadNum: 用于指定线程数目。通常我们希望能使用一个数组指定多个值,这样,我们可以了解程序是否在单线程,较少线程,以及大量线程的情况下是否工作正常。 用于整个 TestCase 来指定测试所用的并行设置 用于指定整个TestCase的并行设置

  InitFor指定此方法服务的测试方法 用于指定初始化方法所服务的并行测试方法

  Threaded 无参数,或定义与 @Test 兼容的参数 用于一个具有两个int类型的测试方法。测试过程中,测试框架将会线程序号以及线程总数通过方法的参数传递进来。这有点类似于 MPI 的约定。 指明一个方法为并行测试方法,相当于JUnit原有的@Test注释。

  CheckFor一个字符串参数,用于指定需要被验证的并行测试方法。 一个Threaded修饰的方法 指明一个方法用于检测并行执行的结果 . 我们不能在Threaded方法中直接检查,因为其他线程的测试也许还没有结束。

  扩展JUnit的过程说明

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

  言归正传,我们扩展JUnit的过程主要由以下过程组成:

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

  生成 TestClassRunner 的子类 Parallelized 并在其中实现运行自定义测试的逻辑

  生成 TestMethodRunner 的子类供 Parallelized 类使用

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

  结论

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

0
相关文章