dotnet watch
コマンドを使ってLive Unit TestっぽくTDDする話です。
はじめに
Visual Studio 2017以降Live Unit Testなる機能があります。
これはコードの変更中にバックグラウンドで自動的に実行し、結果をVisual Studio上に表示する、という機能です。
残念ながら使用するにはVisual Studio Enterprise エディションが必要です。
参考 Microsoft Docs - Visual Studio での Live Unit Testing
弊社はソフト側のエンジニアの地位が弱く、中々予算が下りないのでEnterpriseエディションなんて持ってる人いません。。
なので、ここはdotnet watch
でなんちゃってLive Unit Testをします。
dotnet watchとは
ソースファイルや.csporjで指定したファイルが更新された際に自動的に.NET CLIコマンドを実行するツールです。
Visual Studio Codeでのやり方
Consoleアプリと、単体テストプロジェクトを作成します。
mkdir watchSample cd watchSample dotnet new sln dotnet new console -o sampleApp dotnet new xunit -o UnitTest dotnet sln watchSample.sln add .\sampleApp\sampleApp.csproj dotnet sln watchSample.sln add .\UnitTest\UnitTest.csproj dotnet add .\UnitTest\UnitTest.csproj reference .\sampleApp\sampleApp.csproj code .
単体テストを先に書きます。
UnitTest\UnitTest1.cs
using System; using sampleApp; using Xunit; namespace UnitTest { public class UnitTest1 { [Fact] public void Test1() { Assert.Equal(2, Hoge.Sum(1, 1)); } } }
まだテスト対象の関数を作っていませんが、UnitTestプロジェクトに対してdotnet watch
を使用します。
cd UnitTest dotnet watch test
するとコンソールにこんな感じの表示がされるはずです。
ビルドが通っていないですね。 sampleAppにHogeクラスとSum関数を追加します。
sampleApp/Program.cs
using System; namespace sampleApp { class Program { static void Main(string[] args) { Console.WriteLine("Hello World!"); } } public class Hoge { public static int Sum(int x, int y) => 0; } }
追加した後ファイルを保存します。 ファイルを保存したタイミングで自動的に単体テストが実行されます。
テストに失敗してるらしいです。
いい感じですね。
関数の中身を書いて、テストを通しましょう。
using System; namespace sampleApp { class Program { static void Main(string[] args) { Console.WriteLine("Hello World!"); } } public class Hoge { public static int Sum(int x, int y) => x + y; } }
設定ファイルを監視対象にする
デフォルトだと以下のファイルが監視対象となっています。
- */.cs
- *.csproj
- */.resx
例えばappSetting.jsonなどの設定ファイルが変更された際も自動的に単体テストが走るようにしたい場合、csprojを変更することで対応できます。
以下の例ではbin, objフォルダ以外の全jsonファイルを対象にしています。
ファイルはUnitTest側の.csprojを編集します。
UnitTest/UnitTest.csproj
<Project Sdk="Microsoft.NET.Sdk"> <PropertyGroup> <TargetFramework>netcoreapp3.0</TargetFramework> <IsPackable>false</IsPackable> </PropertyGroup> <ItemGroup> <PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.2.0" /> <PackageReference Include="xunit" Version="2.4.0" /> <PackageReference Include="xunit.runner.visualstudio" Version="2.4.0" /> <PackageReference Include="coverlet.collector" Version="1.0.1" /> </ItemGroup> <ItemGroup> <ProjectReference Include="..\sampleApp\sampleApp.csproj" /> </ItemGroup> <!-- 追加 --> <ItemGroup> <Watch Include="..\**\*.json" Exclude="..\**\bin\**\*.json;..\**\obj\**\*.json" /> </ItemGroup> <!-- 追加 --> </Project>
appSetting.jsonファイルをsampleApp側に追加して、jsonファイルを更新してみましょう。 自動的に単体テストが走るはずです。
特定のファイルを監視対象から外す
ウォッチするファイルのオプトアウトから引用するとこんな感じらしい。
<ItemGroup> <!-- exclude Generated.cs from dotnet-watch --> <Compile Include="Generated.cs" Watch="false" /> <!-- exclude Strings.resx from dotnet-watch --> <EmbeddedResource Include="Strings.resx" Watch="false" /> <!-- exclude changes in this referenced project --> <ProjectReference Include="..\ClassLibrary1\ClassLibrary1.csproj" Watch="false" /> </ItemGroup>
おわり
Microsoft Docsを見ると.NET Coreと.NET Frameworkが混合したソリューションでも使えるっぽいですね。
また、watch
コマンドはテストだけじゃなくdotnet watch run
で
ファイル更新時に自動的にビルド & 起動する、なんてこともできます。
Enterpriseエディションが買えない人もwatch
コマンドで少しでもTDDが楽になるとよいですね。