对调度程序进行单元测试有哪些策略?

问题描述 投票:13回答:5

这篇文章的开头是“单元测试多线程代码中常见的模式有哪些?”,但我在SO上发现了一些other discussions,它们普遍同意“It is Hard(TM)”和“It Depends(TM)”。所以我认为减少问题的范围会更有用。

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

方面:

  • 我还没有找到一种方法来依靠公共接口(像addJob(jobSchedule, jobArgs,jobListener)removeJob(jobId))来测试这个调度程序。
  • 如何根据指定的时间表计算作业被调用的事实?
java multithreading unit-testing
5个回答
6
投票

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

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

4
投票

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

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


3
投票

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

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

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

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


1
投票

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

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

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


1
投票

如果调度程序委托ExecutorExecutorService来运行任务,则可以使用依赖注入来删除对Executor类型的直接依赖,并使用use a simple single threaded Executor来测试调度程序的大部分功能,而不会出现真正的多线程代码的复杂性。一旦你调试了这些测试,你就可以继续前进,但现在大幅度减少测试线程安全的任务。

© www.soinside.com 2019 - 2024. All rights reserved.