Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
.net 对多线程应用程序进行单元测试?_.net_Multithreading_Unit Testing - Fatal编程技术网

.net 对多线程应用程序进行单元测试?

.net 对多线程应用程序进行单元测试?,.net,multithreading,unit-testing,.net,Multithreading,Unit Testing,有人对一致的多线程应用程序单元测试方法有什么建议吗?我做过一个应用程序,其中我们的模拟“工作线程”有一个thread.sleep,时间由公共成员变量指定。我们可以使用它来设置一个特定线程完成其工作所需的时间,然后我们可以进行断言。有没有更好的办法?任何好的.Net模拟框架都可以处理这个问题吗?(商业版)有一个单元测试框架,可以自动尝试在多线程应用程序中查找死锁,我认为可以设置为使用可预测的上下文切换运行线程 我在本周的一个节目中看到了一个演示——显然是在Alpha(叫做Racer)中 不完全是单

有人对一致的多线程应用程序单元测试方法有什么建议吗?我做过一个应用程序,其中我们的模拟“工作线程”有一个thread.sleep,时间由公共成员变量指定。我们可以使用它来设置一个特定线程完成其工作所需的时间,然后我们可以进行断言。有没有更好的办法?任何好的.Net模拟框架都可以处理这个问题吗?

(商业版)有一个单元测试框架,可以自动尝试在多线程应用程序中查找死锁,我认为可以设置为使用可预测的上下文切换运行线程

我在本周的一个节目中看到了一个演示——显然是在Alpha(叫做Racer)中


不完全是单元测试,但您可以编写一些测试代码,重复调用将在不同线程上执行的代码。尝试通过定期或最终一致性检查在线程之间创建最大交错。当然,这种方法的缺点是不可复制,因此您需要使用大量日志来找出哪里出了问题。这种方法最好与每个线程单独任务的单元测试结合起来。

与GUI单元测试一样,对于自动化测试来说,这有点像滑铁卢。根据定义,真正的线程是。。不可预知的他们会以无法预先确定的方式进行干预。因此,编写true测试即使不是不可能,也是很困难的

然而你有一些公司与此。。。我建议搜索testdrivendevelopment雅虎集团的档案。我记得附近有几根柱子。。
(如果有人愿意删去并解释……那太好了。我太困了……需要这样做)

如果你必须测试后台线程是否有作用,我发现一个简单的方法是使用WaitUntilTrue方法,它看起来像这样:

bool WaitUntilTrue(Func<bool> func,
              int timeoutInMillis,
              int timeBetweenChecksMillis)
{
    Stopwatch stopwatch = Stopwatch.StartNew();

    while(stopwatch.ElapsedMilliseconds < timeoutInMillis)
    {
        if (func())
            return true;
        Thread.Sleep(timeBetweenChecksMillis);
    }   
    return false;
}
volatile bool backgroundThreadHasFinished = false;
//run your multithreaded test and make sure the thread sets the above variable.

Assert.IsTrue(WaitUntilTrue(x => backgroundThreadHasFinished, 1000, 10));

这样,您就不必让主测试线程长时间休眠,以便给后台线程足够的时间来完成测试。如果后台没有在合理的时间内完成,测试将失败。

我的建议是,出于以下几个原因,不要依赖单元测试来检测并发性问题:

  • 缺乏再现性:测试偶尔会失败一次,对查明问题没有帮助
  • 不稳定的失败构建会惹恼团队中的每个人,因为最后一次提交总是被错误地认为是失败构建的原因
  • 遇到死锁时,可能会冻结生成,直到遇到执行超时,这会显著降低生成速度
  • 构建环境可能是一个单CPU环境(想想在VM中运行的构建),在这个环境中,并发性问题可能永远不会发生——不管设置了多少睡眠时间
  • 它在某种程度上挫败了使用简单、独立的验证代码单元的想法

在多处理器机器上测试多线程代码非常重要。双核机器可能不够。我见过死锁发生在4处理器机器上,而不是发生在双核单处理器上。然后,您需要创建一个基于客户机程序的压力测试,该客户机程序生成许多线程,并针对目标应用程序发出多个请求。如果客户端计算机也是多处理器的,那么目标应用程序的负载就更大,这会有所帮助。

第一步是要意识到,单元测试所需的大部分代码通常与线程正交。这意味着您应该尝试将执行工作的代码与执行线程的代码分开。完成后,您可以使用正常的单元测试实践轻松地测试完成工作的代码。但你当然知道

问题是测试问题的线程方面,但至少现在你有了一个点,这个线程与执行工作的代码接口,希望你有一个可以模拟的接口。现在您有了线程代码调用的代码的模拟,我发现最好的方法是向模拟中添加一些事件(这可能意味着您需要手动滚动模拟)。然后,这些事件将用于允许测试与正在测试的线程代码同步并阻止该代码

例如,假设我们有一个非常简单的东西,一个处理工作项的多线程队列。你会嘲笑工作项。接口可能包含线程调用以执行工作的“Process()”方法。你在里面放了两个事件。一个是调用Process()时模拟设置的,另一个是在设置第一个事件后模拟等待的。现在,在测试中,您可以启动队列,发布模拟工作项,然后等待工作项的“我正在处理”事件。如果您测试的只是调用该进程,那么您可以设置另一个事件并让线程继续。如果您正在测试更复杂的东西,比如队列如何处理多个分派之类的,那么您可能会在释放线程之前执行其他操作(比如post和等待其他工作项)。因为您可以在测试中等待一个超时,所以您可以确保(比如)只有两个工作项被并行处理,等等。关键是您使用线程代码阻塞的事件使测试具有确定性,以便测试可以控制它们何时运行

我相信您的情况会更复杂,但这是我用来测试线程代码的基本方法,而且效果非常好。如果模拟出正确的位并加入同步点,您可以对多线程代码进行惊人的控制


这里有一些关于这类事情的信息,虽然它是关于C++代码库:

我不认为单元测试是找到线程错误的有效方法,但是它们可以是一个演示已知的THE的好方法。