有没有人对多线程应用程序进行单元测试的一致方法有什么建议?我做过一个应用程序,我们的模拟“工作线程”有一个thread.sleep,它的时间由一个公共成员变量指定。我们将使用它来设置一个特定线程需要多长时间来完成它的工作,然后我们就可以进行断言了。有没有更好的方法呢?有没有好的.Net模拟框架可以处理这个问题?
发布于 2008-09-21 19:17:34
我的建议是不要依赖单元测试来检测并发问题,原因有几个:
发布于 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
发布于 2008-09-21 19:09:47
如果你必须测试一个后台线程做了什么,我发现一个简单的技术很方便,那就是有一个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));这样你就不必让你的主测试线程休眠很长一段时间,让后台线程有时间完成。如果后台没有在合理的时间内完成,测试就会失败。
https://stackoverflow.com/questions/111676
复制相似问题