对调度程序进行unit testing有哪些策略?

这篇文章的开头是“unit testingmultithreading代码中常见的模式有哪些?”,但我发现其他一些关于SO的讨论通常同意“It is Hard(TM)”和“It Depends(TM)”。 所以我认为减少问题的范围会更有用。

背景 :我们正在实现一个简单的调度程序,它为您提供了一种在启动和停止作业时注册回调的方法,当然还可以配置调度的频率。 目前,我们正在围绕java.util.Timer创建一个轻量级包装器。

方面

  • 我还没有找到一种方法来依赖公共接口来测试这个调度程序(类似于addJob(jobSchedule, jobArgs,jobListener)removeJob(jobId) )。

  • 如何根据指定的时间表计算作业的时间?

您可以使用记录器对象记录调度程序的每个unit testing中的顺序,时间和其他有用的东西。 测试很简单:

  1. 创建一个记录器对象
  2. 配置计划
  3. 执行unit testing
  4. 检查记录器对象是否与计划“兼容”

还有一点要记住,你不需要测试Timer是否有效。 您可以编写一个模拟版本的Timer(通过扩展类或使用EasyMock ),它只是检查您是否正确调用它,甚至可能替换为您根本不需要线程。 在这种情况下,如果您的作业侦听器有足够的回调来跟踪调度程序,那么可能需要的工作量超过需要的工作量。

另一个需要记住的重要事项是,在测试调度程序时,使用跟踪调度程序工作方式的自定义作业; 在测试预定作业时,直接调用回调而不是通过调度程序。 您可能有更高级别的集成测试,可以根据系统一起检查两者。

这样的调度程序可能会出现许多故障模式,并且每种模式都很可能需要自己的测试用例。 这些测试用例可能非常不同,所以“这取决于”。

为了测试Java中的并发软件,我推荐JavaOne 2007中的这个演示文稿: 测试并发软件 。

为了测试调度程序必须按照其计划准确执行作业,我将创建一个时间抽象本身。 我在我的一个项目中做过类似的事情,我有一个时间或时钟界面。 默认实现将是MillisecondTime,但在测试期间,我将使用TickTime将其切换出来。 这个实现将允许我的unit testing控制时间的进展和多少。

这样,您可以编写一个测试,其中作业计划每10个刻度运行一次。 然后你的测试只是推进滴答计数器并检查以确保作业以正确的滴答运行。

测试并发代码的几种方法。

  • 在负载下多次运行相同的代码,偶尔会出现一些错误,但如果反复执行则会出现一致的错误。
  • 将不同线程/作业的结果存储在诸如BlockingQueue之类的集合中。 这将允许您检查当前线程中的结果并及时完成(没有丑陋的任意睡眠语句)

如果您发现测试并发性很困难,请考虑重构您的对象/组件以使其更容易测试。