.NET で 単体テストと言えば、いまや xUnit.net が事実上の標準となっている。
ASP.NET Core や .NET Core のドキュメントでも、単体テストは xUnit.net を使うように案内されている。
ところが Visual Studio の Express Edition 系列 の テストエクスプローラは、 xUnit.net に対応していない。
それでも Full .NET Framework や dnx では、そのままテストプロジェクトを「実行」してしまえば、とりあえずデバッグ実行はできていた。
しかし、 .NET Core + dotnet-test-xunit では、それすらもできなくなってしまい、 dotnet test
コマンドの出力を確認するしかなくなってしまった。
デバッグ実行ができないのは流石に不便… ということで、デバッグ実行を行うハックを紹介しよう。
# ライセンス的に Visual Studio Community 使えるのなら、そちらを使うべき。
# ただ、たとえ Express ではなくても、 この方法を使うと xUnit.net の出力が文字化けする問題も防げるぞ。
エントリーポイントを作成し、コンソールプロジェクトにする
Getting started with xUnit.net (.NET Core / ASP.NET Core) > xUnit.net にも書かれているとおり、 テストプロジェクトは 通常 クラスライブラリとしてプロジェクトを作成するが、 Express でデバッグしたいときは エントリーポイント を作成して、コンソールプロジェクトとして作成する。
project.json
:
{
"version": "1.0.0-*",
"buildOptions": {
"emitEntryPoint": true
},
"testRunner": "xunit",
"dependencies": {
"xunit": "2.1.0",
"dotnet-test-xunit": "1.0.0-rc2-build10025"
},
"frameworks": {
"netcoreapp1.0": {
"dependencies": {
"Microsoft.NETCore.App": {
"type": "platform",
"version": "1.0.0-rc2-3002702"
},
"System.Text.Encoding.CodePages": "4.0.1-rc2-24027"
},
"imports": [
"dnxcore50",
"portable-net45+win8"
]
}
}
}
そして、 Visual Studio のプロジェクトの設定で、デバッグ時にプロジェクト自体が起動するように設定してやる。
自分自身の DLL のパスを引数に、 Xunit Runner のメイン関数を呼ぶ
あとは、テストコードにもエントリーポイント作成して、 自分自身の DLL のパスを Xunit.Runner.DotNet.Program.Main の第一引数にしてやれば良い。
.NET Core での コンソールアプリの文字化けを直す で紹介したように、このまま実行すると 非Ascii 文字が文字化けしてしまうので、 ついでに CodePagesEncodingProvider を登録してしまおう。
using System.Linq;
using System.Text;
using Xunit;
namespace netcore_xunit_test_01 {
public class Program {
[Fact]
public static void MethodTest() {
Assert.True(true);
}
// entry point
static int Main(string[] args) {
// Unicode, ASCII, CodePage 28591 (西ヨーロッパ言語) 以外は規定ではサポートしていない
// 初めて Console を使用する前に、 CodePagesEncodingProvider に登録する
Encoding.RegisterProvider(CodePagesEncodingProvider.Instance);
var dllPath = System.Reflection.Assembly.GetEntryAssembly().Location;
return Xunit.Runner.DotNet.Program.Main(new string[] { dllPath }.Concat(args).ToArray());
}
}
}
これで、デバッグ実行ができるようになった。
デバッグ時の引数に 任意の引数を設定してやれば、 dotnet test コマンドを実行した場合と同様、 テスト対象を クラスや名前空間に絞って行うことも可能だ。