并行运行单元测试的启示
作者:网络转载 发布时间:[ 2012/4/13 11:03:14 ] 推荐标签:
我们希望采用并行的方式在本地运行单元测试,从而减少测试时间,提高开发人员的工作效率。我们使用了线程池来提供多线程的并行任务。通过配置启动多个线程,并以程序集为单位,启动TestRunner:
var executorWrapper=newExcetorWrapper(assemblyName,null,false);
var testRunner=newTestRunner(executorWrapper,newRunnerLoggerWrapper());
testRunner.RunAssembly();
其中的RunnerLoggerWrapper是一个自定义的类,实现了Xunit的IRunnerLogger。XUnit的使用并非本文描述的内容,在此略过。
因为是以程序集为单位,所以我们在启动多线程之前,会事先将需要运行的程序集放到一个队列中,然后在启动多线程之后,执行出队列操作。多线程的运行代码如下所示:
privatestaticManualResetEvent[] resetEvents;
privatestaticQueue
privatestaticreadonlyObject LockAssembly2Queue=newObject();
publicvoidRun()
{
for(var index=0; index
{
resetEvents[index]=newManualResetEvent(false);
ThreadPool.QueueUserWorkItem(DoWork, index);
}
WaitForAllManualEvent();
}
privatevoidWaitForAllManualEvent()
{
if(Thread.CurrentThread.ApartmentState=ApartmentState.STA)
{
foreach(var manualResetEventinresetEvents)
{
WaitHandle.WaitAny(newWaitHandle[]{manualResetEvent});
}
}
else
{
WaitHandle.WaitAll(resetEvents);
}
}
privatestaticvoidDoWork(Object index)
{
Thread.CurrentThread.ApartmentState=ApartmentState.STA;
while(true)
{
stringcurrentAssemblyName=null;
lock(LockAssembly2Queue)
{
if(assemblyQue.Count!=0)
{
currentAssemblyName=assemblyQue.Dequeue();
}
else
{
resetEvents[(int)index].Set();
Console.WriteLine("Exited current thread:{0}", Thread.CurrentThread.Name);
break;
}
}
if(currentAssemblyName!=null)
{
newTestRunnerWrapperWithAssembly(currentAssemblyName).Runner();
}
}
}

sales@spasvo.com