首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >对多线程应用程序进行单元测试?

问对多线程应用程序进行单元测试?
EN

Stack Overflow用户
提问于 2008-09-21 18:43:20
回答 9查看 10.1K关注 0票数 33

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

EN

回答 9

Stack Overflow用户

回答已采纳

发布于 2008-09-21 19:17:34

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

  • 缺乏重复性:测试只会偶尔失败一次,
  • 构建环境很可能是单problems.
  • Erratic环境(假设构建是在虚拟机中运行的),其中的并发问题可能永远不会发生--无论设置多少休眠时间。
  • 它以某种方式击败了简单、验证代码的独立单元。
票数 24
EN

Stack Overflow用户

发布于 2008-09-26 08:35:17

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

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

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

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

下面是关于这类事情的更多信息,尽管它是关于C++代码库:http://www.lenholgate.com/blog/2004/05/practical-testing.html

票数 31
EN

Stack Overflow用户

发布于 2008-09-21 19:09:47

如果你必须测试一个后台线程做了什么,我发现一个简单的技术很方便,那就是有一个WaitUntilTrue方法,看起来像这样:

代码语言:javascript
复制
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;
}

如下所示:

代码语言:javascript
复制
volatile bool backgroundThreadHasFinished = false;
//run your multithreaded test and make sure the thread sets the above variable.

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

这样你就不必让你的主测试线程休眠很长一段时间,让后台线程有时间完成。如果后台没有在合理的时间内完成,测试就会失败。

票数 11
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/111676

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档