I needed to put 2 test assemblies into my automated CruiseControl.NET build and get coverage results. It appears that this is a pretty common need, with some tricks to get things working properly. According to http://www.kiwidude.com/blog/2006/10/ncoverexplorer-merging-ncover-reports.html, you need to either use an NUnit project file to contain all of the unit tests or merge the coverage xml files in the NCoverExplorer task.
NUnit project setup and problems
By using an NUnit project file, all of the tests are executed within one call, which produces one coverage.xml file. This allows tests from multiple test assemblies to be merged together into one coverage file that NCoverExplorer will understand automatically.
<TestAssemblies Include="MyApp.Tests.nunit" />
MyApp.Tests.nunit contents:
<NUnitProject>
<Config name="Default" binpathtype="Auto">
<assembly path="MyApp.DAL.Test\bin\Debug\MyApp.DAL.Test.dll" />
<assembly path="MyApp.Service.Test\bin\Debug\MyApp.Service.Test.dll" />
</Config>
</NUnitProject>
The major downside of this approach is that, according to http://nunit.com/blogs/?p=9, when using the NUnit project file, the config file that gets loaded needs to be based off of the NUnit project filename (i.e. in this case, MyAppT.Tests.config) and not the individual test assembly filenames. This means that we need to continually merge all of the app.config files into one "master" config file. This is not exactly a long-term, maintainable solution.
NCoverExplorer task setup
That brings us to the second possible solution presented above, namely to merge multiple coverage files together. To do this, you need to take some care in how you set the properties up for the tasks so that you don't overwrite coverage output files. My current build project looks similar to the one below. One other thing to keep in mind is to include the *.CoverageMerge.xml file in your CC.NET config file's <merge> section for this project.
<ItemGroup>
<TestAssemblies Include="$(DALTestAssembly)" />
<TestAssemblies Include="$(ServiceTestAssembly)" />
<NCoverAssemblies Include="$(DALAssembly)" />
<NCoverAssemblies Include="$(ServiceAssembly)" />
<NCoverCoverageFiles Include="**.Coverage.xml" />
</ItemGroup>
<Target Name="Test" DependsOnTargets="CoreBuild">
<NCover ToolPath="lib\NCover\"
CommandLineArgs="%(TestAssemblies.FullPath) /xml=%(TestAssemblies.Filename).xml /labels /nologo"
CommandLineExe="lib\NUnit\nunit-console.exe"
CoverageFile="%(TestAssemblies.Filename).Coverage.xml"
LogFile="%(TestAssemblies.Filename).Coverage.log"
LogLevel="Verbose"
WorkingDirectory="$(MSBuildProjectDirectory)"
Assemblies="@(NCoverAssemblies)"
/>
<NCoverExplorer
ProjectName="MyApp"
ReportType="ModuleClassSummary"
OutputDir="$(MSBuildProjectDirectory)"
XmlReportName="MyApp.CoverageSummary.xml"
HtmlReportName="MyApp.CoverageSummary.html"
ShowExcluded="True"
SatisfactoryCoverage="80"
CoverageFiles="@(NCoverCoverageFiles)"
MergeFileName="MyApp.CoverageMerge.xml"
ToolPath="lib\NCover\Explorer"
/>
</Target>