我应该如何测试线程代码?
迄今为止,我避免了测试多线程代码的噩梦,因为它看起来像是一个雷区。 我想问一下,人们是如何测试依赖线程执行成功执行的代码的,或者人们是如何测试那些只有当两个线程以给定的方式进行交互时才会显示的问题的方式?
这对于今天的程序员来说似乎是一个非常关键的问题,将我们的知识集中在这一个imho上会非常有用。
看,有没有简单的方法来做到这一点。 我正在开发一个固有多线程的项目。 事件来自操作系统,我必须同时处理它们。
处理测试复杂的多线程应用程序代码的最简单的方法是:如果测试过于复杂,那么你做错了。 如果您有一个具有多个线程的单个实例,并且您无法测试这些线程是否遍布彼此的情况,那么您的设计需要重做。 它既简单又复杂。
有很多方法可以为多线程编程,避免线程同时在实例中运行。 最简单的是让所有的对象不可变。 当然,这通常是不可能的。 所以你必须在你的设计中确定线程与同一个实例交互的地方,并减少这些地方的数量。 通过这样做,您可以隔离实际发生多线程的几个类,从而降低测试系统的总体复杂性。
但是你必须认识到,即使这样做,你仍然无法测试两个线程彼此接触的情况。 要做到这一点,你必须在同一个测试中同时运行两个线程,然后准确控制他们在任何给定时刻执行的线路。 你能做的最好的就是模拟这种情况。 但是这可能要求您专门为测试编写代码,而这只是朝着真正的解决方案迈出了一大步。
测试线程问题代码的最好方法可能是通过代码的静态分析。 如果您的线程代码不遵循有限的线程安全模式集,那么您可能会遇到问题。 我相信VS中的代码分析确实包含了线程的一些知识,但可能并不多。
按照目前的情况来看(可能会迎来一个好时机),测试多线程应用程序的最佳方法是尽可能减少线程代码的复杂性。 尽量减少线程交互的区域,尽可能进行最佳测试,并使用代码分析来识别危险区域。
发布这个问题已经有一段时间了,但它仍然没有回答...
kleolb02的回答是一个很好的答案。 我会尝试进入更多细节。
有一种方法,我为C#代码练习。 对于单元测试,您应该能够对可重复测试进行编程,这是多线程代码中最大的挑战。 所以我的答案旨在强制异步代码进入同步工作的测试工具。
这是Gerard Meszardos的书“xUnit Test Patterns”中的一个想法,被称为“Humble Object”(p。695):您必须将核心逻辑代码和任何闻起来像异步代码的东西分开。 这将导致核心逻辑的类同步工作。
这使您能够以同步方式测试核心逻辑代码。 您可以绝对控制您在核心逻辑上进行的调用的时间,从而可以进行可重复的测试。 这是分离核心逻辑和异步逻辑的好处。
这个核心逻辑需要被另一个类包围,这个类负责异步接收对核心逻辑的调用,并将这些调用委托给核心逻辑。 生产代码只能通过该类访问核心逻辑。 因为这个类只能委托调用,所以它是一个非常“愚蠢”的类,没有太多的逻辑。 所以你可以保持对这个异步工作类的单元测试至少。
以上任何东西(测试类之间的交互)都是组件测试。 同样在这种情况下,如果您坚持“谦虚对象”模式,您应该能够对时间进行绝对控制。
确实很难! 在我的(C ++)单元测试中,我已经沿着所使用的并发模式分成了几类:
单元测试在单线程中运行并且不能识别线程的类 - 简单,像往常一样测试。
Monitor对象(在调用者的控制线程中执行同步方法的那些对象)的单元测试公开了一个同步的公共API - 实例化多个模拟线程来执行API。 构建锻炼被动对象内部条件的场景。 包括一个较长时间的运行测试,基本上可以在很长一段时间内从多个线程跳出来。 这是我知道的不科学的,但它确实建立了信心。
Active对象的单元测试(封装自己的线程或控制线程的那些) - 类似于上面的#2,具体取决于类设计。 公共API可能是阻塞的或非阻塞的,呼叫者可能获得期货,数据可能到达队列或需要出队。 这里有很多可能的组合; 白色的盒子。 仍然需要多个模拟线程来调用被测对象。
作为旁白:
在我所做的内部开发人员培训中,我教授了并发支柱,并将这两种模式作为思考和分解并发问题的主要框架。 显然有更先进的概念,但我发现这套基础知识可以帮助工程师摆脱困境。 如上所述,它还会导致更多单元可测试的代码。
链接地址: http://www.djcxy.com/p/8961.html