代码之家  ›  专栏  ›  技术社区  ›  Joonas Pulakka

单元测试实时/并发软件[副本]

  •  27
  • Joonas Pulakka  · 技术社区  · 15 年前

    可能重复:
    How should I unit test threaded code?

    经典的单元测试基本上只是将x放入并期望y退出,并使该过程自动化。所以它对测试任何 不涉及时间 . 但是,我遇到的大多数不平凡的错误都与时间有关。线程会损坏彼此的数据,或导致死锁。不确定性行为在百万分之一的时间内发生。硬东西。

    对于多线程并发系统的“单元测试”部分有什么有用的吗?这种测试是如何工作的?是否有必要长时间运行此类测试的主题,并以某种巧妙的方式改变环境,从而合理地相信它工作正常?

    6 回复  |  直到 14 年前
        1
  •  12
  •   Charles Salvia    15 年前

    我现在做的大多数工作都涉及多线程和/或分布式系统。大多数错误涉及“发生在”类型错误之前,开发人员 假设 (错误地)事件A总是发生在事件B之前。但是每运行程序1000000次,事件B首先发生,这会导致不可预测的行为。

    此外,还没有真正好的工具来检测时间问题,甚至是由竞争条件导致的数据损坏。像valgrind工具包中的helgrind和drd这样的工具对于小程序非常有用,但是它们在诊断大型复杂系统时并不十分有用。一方面,他们经常报告假阳性(尤其是赫尔格林)。另一方面,在helgrind/drd下运行时,很难实际检测到某些错误,因为在helgrind下运行的程序运行速度慢了近1000倍,而且您经常需要运行一个程序很长的时间,甚至 复制 比赛条件。此外,由于在Helgrind下运行完全改变了程序的时间,它可能会 不可能的 重现某个时间问题。这就是微妙的时间问题的问题;他们几乎是海森堡式的,从某种意义上说,改变一个程序来检测时间问题可能会掩盖最初的问题。

    可悲的是,人类还没有充分准备好处理复杂的并发软件。所以不幸的是,没有一种简单的方法可以对其进行单元测试。尤其是对于分布式系统,您应该使用 Lamport's happens-before diagrams 帮助您确定程序中事件的必要顺序。但是,最终,您不能真正摆脱带有随机变化输入的蛮力单元测试。它还有助于在单元测试期间通过改变线程上下文切换的频率,例如运行另一个只占用CPU周期的后台进程。此外,如果您有权访问集群,您可以并行运行多个单元测试,这样可以更快地检测错误并节省大量时间。

        2
  •  5
  •   Jeremy Friesner    15 年前

    如果您可以在Linux下运行测试,valgrind包含一个名为 helgrind 它的目的是检测使用pthreads的程序中的竞争条件和潜在死锁;在这种情况下运行多线程代码可能会带来一些好处,因为即使在特定的测试运行中没有实际发生潜在的错误,它也会报告潜在的错误。

        3
  •  4
  •   Community dbr    7 年前

    我从来没有听说过任何可能的事情。

    我猜如果有人要设计一个线程,它必须对线程的执行有精确的控制,并执行线程的所有可能的步进组合。

    听起来像是一项重要的任务,更不用说当有少数线程或更多线程时,它们的数学组合会非常重要…

    不过,快速搜索stackoverflow… Unit testing a multithreaded application?

        4
  •  3
  •   Lycha    15 年前

    如果测试系统足够简单,您可以通过阻塞外部模型系统中的操作来很好地控制并发性。例如,可以通过等待启动其他操作来完成此阻塞。如果您可以控制所有外部调用,那么通过实现不同的阻塞序列,这可能会很好地工作。我已经尝试过了,如果您很好地了解可能存在问题的序列,它确实可以很好地揭示锁级错误。与许多其他并发测试相比,它是非常确定的。然而,这种方法不能很好地检测到低水平的比赛条件。我通常只是去进行负载测试来找到它们,但我觉得这不完全是单元测试。

    我已经看到了.NET的这些并发测试框架,我假设在某人为Java编写一个(希望)的时候只是时间问题。

    别忘了读好的旧代码。找到并发错误的最好方法之一就是再次阅读代码,让它完全集中于您的注意力。

        5
  •  1
  •   AndyM    14 年前

    也许答案是你不应该这样做。在并发系统中,可能并不总是有一个确定的答案是正确的。

    以人们登上火车并选择座位为例。每次你都会得到不同的结果。

        6
  •  1
  •   Johan    14 年前

    Awaitility 当您需要在测试中处理异步性时,它是一个有用的框架。它允许您等待系统中的某个状态被更新。例如:

    await().untilCall( to(myService).myMethod(), equalTo(3) );
    

    await().until( fieldIn(myObject).ofType(int.class), greaterThan(1));
    

    它还支持scala和groovy。