我们希望采用并行的方式在本地运行单元测试,从而减少测试时间,提高开发人员的工作效率。我们使用了线程池来提供多线程的并行任务。通过配置启动多个线程,并以程序集为单位,启动TestRunner:

var executorWrapper=newExcetorWrapper(assemblyName,null,false);

var testRunner=newTestRunner(executorWrapper,newRunnerLoggerWrapper());

testRunner.RunAssembly();

其中的RunnerLoggerWrapper是一个自定义的类,实现了Xunit的IRunnerLogger。XUnit的使用并非本文描述的内容,在此略过。

因为是以程序集为单位,所以我们在启动多线程之前,会事先将需要运行的程序集放到一个队列中,然后在启动多线程之后,执行出队列操作。多线程的运行代码如下所示:

privatestaticManualResetEvent[] resetEvents;

privatestaticQueueassemblyQue;

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();

}

}

}