.NET Coreでの自動テスト
.NET Coreは、基本コマンドの中にテストランナーの実行サブコマンドが含みます。project.jsonファイル内に
"testRunner": "..."
という記述をおこなっておくと、プロジェクトディレクトリ内で$ dotnet test
.NETではふつうxUnit使うよね、という風潮
.NET Coreでのテスト実行については公式ヘルプページ(Unit Testing in .NET Core using dotnet test)があります。このドキュメント内にはxUnitを利用する手順しか書かれていません。しかし個人的にはxUnitのキラキラしたオシャレ雰囲気があまり好きではなくて、泥臭さを感じるNUnitのほうが好みです。
.NET Coreのproject.json内での
"testRunner": "foobar"
という記述を解釈したランタイムは、src/dotnet/commands/dotnet-test/ConsoleTestRunner.csに従ってdotnet-test-foobar
というコマンドを探しにいきます。dotnet-test-nunitというコマンドが存在すればいい感じにテストランナーとして呼び出せるはずです。.NET Coreにおけるコマンド解決の方法
コマンドを探しにいきますが、一体どのように対象を解決して実行するのでしょうか。プロジェクトのbinディレクトリもしくはパッケージ参照パスから、一致する名前をもつexeまたはdllを拾ってくることは想像がつきます。具体的にはsrc/Microsoft.DotNet.Cli.Utils/ProjectDependenciesCommandFactory.csを起点とするsrc/Microsoft.DotNet.Cli.Utils/CommandResolutionのコード群による解決がおこなわれます。
コマンド解決部分は1.0.0正式版リリースを前にしてもちょくちょく手が入っているので、正式版が出た後で機会があれば書いてみたいところです。
NUnitの.NET Core向けテストランナーalpha版の使い方
さて、xUnitではなくNUnitを使おうと試行錯誤すること数分、どうやらNUnitの.NET Core対応版がまだリリースされていないらしいことに気付きました。ゴリ押しする方法は提示されています。しかし.NET Core方式のほうが、テストランナーとのレポートのやり取り方法などをきっちり定義しているので、のちのちはCIでの状況モニタなどにおいて下回りのテストランナーを意識せずに結果を利用できるようになって嬉しいはずです。このため、せっかくなら.NET Coreの流儀でやりたいものです*1。実はnuget.orgでNUnitの.NET Core対応alpha版が配布されています*2。
本エントリを書いているタイミングでの最新版は
dotnet-test-nunit/3.4.0-alpha-1
です。使いかたはとてもシンプルです。マルチプロジェクト構成をとる場合は、さきほどのUnit Testing in .NET Core using dotnet testページのxUnit向けガイドに途中まで従ってglobal.jsonを書くなどしておきましょう。
そしてテストプロジェクト側では次のようなproject.jsonファイルを作成します。
{ "version": "1.0.0-*", "dependencies": { "NETStandard.Library": "1.5.0-rc2-24027", "NUnit": "3.2.1", "NUnitLite": "3.2.1", "dotnet-test-nunit": "3.4.0-alpha-1", "ReVIEWBlogger": "1.0.0" }, "testRunner": "nunit", "frameworks": { "netstandard1.5": { "imports": [ "dnxcore50", "netcoreapp1.0", "portable-net45+win8" ] } }, "runtimes": { "win10-x86": {}, "win10-x64": {}, "osx.10.11-x64": {}, "debian.8-x64": {} } }
"ReVIEWBlogger": "1.0.0"
は私の手元のテスト対象パッケージです。手元の環境にあわせて適宜変更してください。大事な記述が数点あるので整理します。
"testRunner": "nunit"
.NET Coreへのテストランナー指定"dependencies"
内"NUnit": "3.2.1"
NUnitの本体"dotnet-test-nunit": "3.4.0-alpha-1"
NUnitの.NET Core用テストランナー
"frameworks": { "netstandard1.5": "imports": [] }
内"portable-net45+win8"
dnxcore50未サポートの依存PCLパッケージ用*3
"runtimes"
実行環境に含めたいランタイムの一覧- テストランナーでxplatというのはまああんまり想定するものでないので、"platform"指定ではなく"platfroms":でそれぞれ指定していく感じです
- 一般的なものはここでカバーしていますが、足りない場合は公式のRID一覧ページを参照してください
ちなみにパス解決の都合上、project.jsonでの記述は
"testRunner": "NUnit"
などではなく"testRunner": "nunit"
と表記する必要があります。私は当初NUnit
と記載していて、以下のように「そんな実行ファイルないよ」と怒られていました。dotnet-test Error: 0 : Microsoft.DotNet.Cli.Utils.CommandUnknownException: No executable found matching command "dotnet-test-NUnit" at Microsoft.DotNet.Cli.Utils.ProjectDependenciesCommandFactory.FindProjectDependencyCommands(String commandName, IEnumerable`1 commandArgs, String configuration, NuGetFramework framework, String outputPath, String buildBasePath, String projectDirectory) at Microsoft.DotNet.Cli.Utils.ProjectDependenciesCommandFactory.Create(String commandName, IEnumerable`1 args, NuGetFramework framework, String configuration) at Microsoft.DotNet.Tools.Test.ConsoleTestRunner.DoRunTests(ProjectContext projectContext, DotnetTestParams dotnetTestParams) at Microsoft.DotNet.Tools.Test.TestCommand.DoRun(String[] args)
[*1] .NET Coreのテストランナーサポートについては、NUnitのGitHubリポジトリにてissue(https://github.com/nunit/nunit/issues/1371が立っていて、nuget.orgで配布を始める前の暫定版も配布されていましたが、このblogエントリを下書きで放置している間にクローズされました。
[*2] 本件を調べ始めた当初にはNUnit開発者のプライベートなNuGetリポジトリにてテスト版が公開されていたのですが、nuget.orgへ移動しました。
[*3] .NET Core環境を想定していないパッケージはまだまだ多いです。実際にはportable-net45+win8指定で問題なく動作するものも多いので、この記述は現在の.NET Core用project.json内で頻出します。
.NET Coreのコマンドラインからテストを実行してみる
次のようなコードを書いて実行してみます。using NUnit.Framework; namespace ConsoleApplication { [TestFixture] public class Program1 { [Test] public void TestExpectedToPass() { Assert.Pass(); } [Test] public void TestExpectedToFail() { Assert.Fail("No luck!!"); } } }
$ dotnet test Project ReVIEWBlogger (.NETCoreApp,Version=v1.0) was previously compiled. Skipping compilation. Project ReVIEWBlogger.Tests (.NETStandard,Version=v1.5) will be compiled because inputs were modified Compiling ReVIEWBlogger.Tests for .NETStandard,Version=v1.5 Compilation succeeded. 0 Warning(s) 0 Error(s) Time elapsed 00:00:06.2825436 NUnit .NET Core Runner 3.4.0 Copyright (C) 2016 Charlie Poole Runtime Environment OS Platform: Darwin OS Version: 10.11 Runtime: osx.10.11-x64 Test Files /Users/muo/workspace/review-blogger/test/ReVIEWBlogger.Tests/bin/Debug/netstandard1.5/osx.10.11-x64/ReVIEWBlogger.Tests.dll Errors and Failures 1) Failed : ConsoleApplication.TestsForTesting.TestExpectedToFail No luck!! at ConsoleApplication.TestsForTesting.TestExpectedToFail() Run Settings WorkDirectory: /Users/muo/workspace/review-blogger/test/ReVIEWBlogger.Tests Test Run Summary Overall result: Failed Test Count: 2, Passed: 1, Failed: 1, Inconclusive: 0, Skipped: 0 Failed Tests - Failures: 1, Errors: 0, Invalid: 0 Start time: 2016-06-13 06:39:19Z End time: 2016-06-13 06:39:19Z Duration: 0.637 seconds Results saved as /Users/muo/workspace/review-blogger/test/ReVIEWBlogger.Tests/TestResult.xml SUMMARY: Total: 1 targets, Passed: 0, Failed: 1.
すばらしい。
すばらしいですね。