FxCop、OpenCover、NUnit を実行する MSBuild ファイル(Report.proj) を作ってみた

NUnit、PartCover を組み合わせた MSBuild ファイル(.proj) を作る (個人的なメモ) - お だ のスペース では、PartCover を使っていましたが、今回は OpenCover を使いました。


次のような構成のソリューションを対象にしています。

  • Sample.sln
    • Sample.WinForms.csproj
    • Sample.Services.csproj
    • Sample.WinForms.Test.csproj
    • Sample.Services.Test.csproj
    • Solution Items
      • Report.proj
      • CodeAnalysis.fxcop


NuGet で、NUnit/NUnit Runners、OpenCover、ReportGenerator をインストールしています。FxCop は NuGet ではインストール出来ないので、Download Microsoft Windows SDK for Windows 7 and .NET Framework 4 from Official Microsoft Download Center 経由でインストール。

ソリューションのプロパティから ReportBuild という構成を追加し(Debug をコピー)、ReportBuild 時は、各プロジェクトの出力先を ../TestDLL に変更しています。*1
FxCop で適用するルールは、FxCop.exe (GUI) で設定した CodeAnalysis.fxcop ファイルを出力し、これを FxCopCmd.exe (CUI) から実行します。

Report.proj

<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" DefaultTargets="ReportBuild" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <PropertyGroup>
    <ProjectName>Sample</ProjectName>
    <!-- FxCop/OpenCover/NUnit の設定 -->
    <FxCopPath>C:\Program Files (x86)\Microsoft Fxcop 10.0\FxCopCmd.exe</FxCopPath>
    <FxCopProjectPath>$(MSBuildProjectDirectory)\CodeAnalysis.fxcop</FxCopProjectPath>
    <FxCopResultPath>$(MSBuildProjectDirectory)\FxCopResult.xml</FxCopResultPath>
    <OpenCoverPath>$(MSBuildProjectDirectory)\packages\OpenCover.4.0.301\OpenCover.Console.exe</OpenCoverPath>
    <NUnitPath>$(MSBuildProjectDirectory)\packages\NUnit.Runners.2.6.0.12051\tools\nunit-console.exe</NUnitPath>
    <TestResultPath>$(MSBuildProjectDirectory)\NUnitResult.xml</TestResultPath>
    <OpenCoverResultPath>$(MSBuildProjectDirectory)\OpenCoverResult.xml</OpenCoverResultPath>
    <NUnitArgs>$(ProjectName).Services.Test.dll $(ProjectName).WinForms.Test.dll /xml=$(TestResultPath) /framework=4.0</NUnitArgs>
    <TargetDir>$(MSBuildProjectDirectory)\TestDLL</TargetDir>
    <Filters>+[$(ProjectName).*]$(ProjectName).* -[$(ProjectName).*]$(ProjectName).*.Test.* -[$(ProjectName).*]$(ProjectName).*.Properties*</Filters>
    <ReportGeneratorPath>$(MSBuildProjectDirectory)\packages\ReportGenerator.1.3.0.0\ReportGenerator.exe</ReportGeneratorPath>
    <ReportGeneratorResultPath>$(MSBuildProjectDirectory)\OpenCoverReport</ReportGeneratorResultPath>
    <ReportGeneratorArgs>"$(OpenCoverResultPath)" $(ReportGeneratorResultPath)</ReportGeneratorArgs>
  </PropertyGroup>
  
  <Target Name="Rebuild">
    <Message Text="Rebuild" />
    <MSBuild Projects="$(MSBuildProjectDirectory)\$(ProjectName).sln"
      Targets="Rebuild;" Properties="Configuration=$(BuildConfig);Platform=Any CPU" />
  </Target>
  
  <!-- FxCop/OpenCover(+NUnit) を実行する -->
  <Target Name="CreateReport">
    <Message Text="Exec FxCop" />
    <Exec Command="&quot;$(FxCopPath)&quot; /p:&quot;$(FxCopProjectPath)&quot; /out:&quot;$(FxCopResultPath)&quot;" />
    <Message Text="Exec OpenCover" />
    <Exec Command="&quot;$(OpenCoverPath)&quot; -register:user -target:&quot;$(NUnitPath)&quot; -targetargs:&quot;$(NUnitArgs)&quot; -targetdir:&quot;$(TargetDir)&quot; -filter:&quot;$(Filters)&quot; -output:&quot;$(OpenCoverResultPath)&quot;" />
    <Message Text="Exec ReportGenerator" />
    <Exec Command="&quot;$(ReportGeneratorPath)&quot; $(ReportGeneratorArgs)" />
  </Target>
  <!-- レポートビルドタスク -->
  <Target Name="ReportBuild" DependsOnTargets="Rebuild;CreateReport;" />
</Project>

FxCop や OpenCover を実行する MSBuild カスタムタスクもあるんですが、今回は標準のタスクだけで書いてます。
Brad Wilson: Writing an FxCop Task for MSBuild
opencover/main/OpenCover.MSBuild at master · sawilde/opencover · GitHub


後はこれを各開発者が開発端末から MSBuild で実行するなり、Jenkins で走らせて NUnit Plugin/Violation Plugin/HTML Publisher Plugin なんかでレポート表示とかですかね。
これなら、各開発環境は、Visual Studio 2010 C# Express で大丈夫ですし、当然 Jenkins サーバーも .NET Framework 4 SDKWindows SDK + FxCop があればビルド出来ます。*2


NUnit + Moles にしようかと思ったんですが、Express だと色々アレなので Moles の利用は見送り。。*3

*1:アセンブリの場所を1箇所にしたいため。ビルド後に Copy Task でかき集めるでも良いのですが、他にも設定を変えるかもしれないので構成を追加しています。

*2:NUnit/OpenCover/ReportGenerator は NuGet 経由でソースリポジトリに放り込んどく

*3:使うなら NuGet で入る Moq かな〜