xUnit チュートリアル
xUnit調査
チュートリアルをやってみる
プロジェクト作成
テスト対象のソリューションファイルを作成する
dotnet new sln -o unit-testing-using-dotnet-test
cd unit-testing-using-dotnet-test
dotnet new classlib -o PrimeService
クラス作成
テスト対象のクラスを作成
using System;
namespace Prime.Services
{
public class PrimeService
{
public bool IsPrime(int candidate)
{
throw new NotImplementedException("Not implemented.");
}
}
}
テストプロジェクト作成
cd unit-testing-using-dotnet-test
dotnet sln add ./PrimeService/PrimeService.csproj
dotnet new xunit -o PrimeService.Tests
ソリューションファイルにテストプロジェクトを追加
PrimeService.Tests プロジェクトへの依存関係として PrimeService クラス ライブラリを追加
dotnet add ./PrimeService.Tests/PrimeService.Tests.csproj reference ./PrimeService/PrimeService.csproj
この時点でのPrimeService.Tests.csproj
テスト対象となるプロジェクトがProjectReference
に登録されている状態
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<IsPackable>false</IsPackable>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.1.0" />
<PackageReference Include="xunit" Version="2.4.1" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.3">
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<PrivateAssets>all</PrivateAssets>
</PackageReference>
<PackageReference Include="coverlet.collector" Version="3.1.2">
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<PrivateAssets>all</PrivateAssets>
</PackageReference>
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\PrimeService\PrimeService.csproj" />
</ItemGroup>
</Project>
テストの作成
テスト駆動開発(TDD)のアプローチ
失敗することがわかっているテストを記述する
不要なファイルを削除
PrimeService.Tests/PrimeService_IsPrimeShould.cs
を作成
using Xunit;
using Prime.Services;
namespace Prime.UnitTests.Services
{
public class PrimeService_IsPrimeShould
{
[Fact]
public void IsPrime_InputIs1_ReturnFalse()
{
var primeService = new PrimeService();
bool result = primeService.IsPrime(1);
Assert.False(result, "1 should not be prime");
}
}
}
[Fact]
属性でテストランナーによって実行されるテストメソッドを宣言PrimeService.Tests
でdotnet test
コマンドでテストランナーを起動する
テストが失敗する
Determining projects to restore...
Restored /Users/***/project/csharp/dotnet_core_xunit/unit-testing-using-dotnet-test/PrimeService.Tests/PrimeService.Tests.csproj (in 726 ms).
1 of 2 projects are up-to-date for restore.
PrimeService -> /Users/***/project/csharp/dotnet_core_xunit/unit-testing-using-dotnet-test/PrimeService/bin/Debug/net6.0/PrimeService.dll
PrimeService.Tests -> /Users/***/project/csharp/dotnet_core_xunit/unit-testing-using-dotnet-test/PrimeService.Tests/bin/Debug/net6.0/PrimeService.Tests.dll
Test run for /Users/***/project/csharp/dotnet_core_xunit/unit-testing-using-dotnet-test/PrimeService.Tests/bin/Debug/net6.0/PrimeService.Tests.dll (.NETCoreApp,Version=v6.0)
Microsoft (R) Test Execution Command Line Tool Version 17.3.1 (x64)
Copyright (c) Microsoft Corporation. All rights reserved.
Starting test execution, please wait...
A total of 1 test files matched the specified pattern.
[xUnit.net 00:00:00.60] Prime.UnitTests.Services.PrimeService_IsPrimeShould.IsPrime_InputIs1_ReturnFalse [FAIL]
Failed Prime.UnitTests.Services.PrimeService_IsPrimeShould.IsPrime_InputIs1_ReturnFalse [2 ms]
Error Message:
System.NotImplementedException : Not implemented.
Stack Trace:
at Prime.Services.PrimeService.IsPrime(Int32 candidate) in /Users/***/project/csharp/dotnet_core_xunit/unit-testing-using-dotnet-test/PrimeService/PrimeService.cs:line 9
at Prime.UnitTests.Services.PrimeService_IsPrimeShould.IsPrime_InputIs1_ReturnFalse() in /Users/***/project/csharp/dotnet_core_xunit/unit-testing-using-dotnet-test/PrimeService.Tests/PrimeService_IsPrimeShould.cs:line 12
Failed! - Failed: 1, Passed: 0, Skipped: 0, Total: 1, Duration: < 1 ms - /Users/***/project/csharp/dotnet_core_xunit/unit-testing-using-dotnet-test/PrimeService.Tests/bin/Debug/net6.0/PrimeService.Tests.dll (net6.0)
テストが合格するようにPrimeService/PrimeService.cs
のIsPrime
メソッドを更新
public bool IsPrime(int candidate)
{
if (candidate == 1)
{
return false;
}
throw new NotImplementedException("Not fully implemented.");
}
テストを実行し、テストが成功したことを確認
dotnet test
Determining projects to restore...
All projects are up-to-date for restore.
PrimeService -> /Users/***/project/csharp/dotnet_core_xunit/unit-testing-using-dotnet-test/PrimeService/bin/Debug/net6.0/PrimeService.dll
PrimeService.Tests -> /Users/***/project/csharp/dotnet_core_xunit/unit-testing-using-dotnet-test/PrimeService.Tests/bin/Debug/net6.0/PrimeService.Tests.dll
Test run for /Users/***/project/csharp/dotnet_core_xunit/unit-testing-using-dotnet-test/PrimeService.Tests/bin/Debug/net6.0/PrimeService.Tests.dll (.NETCoreApp,Version=v6.0)
Microsoft (R) Test Execution Command Line Tool Version 17.3.1 (x64)
Copyright (c) Microsoft Corporation. All rights reserved.
Starting test execution, please wait...
A total of 1 test files matched the specified pattern.
Passed! - Failed: 0, Passed: 1, Skipped: 0, Total: 1, Duration: < 1 ms - /Users/***/project/csharp/dotnet_core_xunit/unit-testing-using-dotnet-test/PrimeService.Tests/bin/Debug/net6.0/PrimeService.Tests.dll (net6.0)
同じコードで違うパラメータをテストする
IsPrime_InputIs1_ReturnFalse
を書き換える
[Theory] 属性で同じコードで「異なる入力引数が含まれる一連のテスト」の実行を表す
[InlineData] 属性で入力値を指定
[Theory]
[InlineData(-1)]
[InlineData(0)]
[InlineData(1)]
public void IsPrime_ValuesLessThan2_ReturnFalse(int value)
{
var result = _primeService.IsPrime(value);
Assert.False(result, $"{value} should not be prime");
}
PrimeService_IsPrimeShould
を更新
public class PrimeService_IsPrimeShould
{
private readonly PrimeService _primeService;
public PrimeService_IsPrimeShould()
{
_primeService = new PrimeService();
}
[Theory]
[InlineData(-1)]
[InlineData(0)]
[InlineData(1)]
public void IsPrime_ValuesLessThan2_ReturnFalse(int value)
{
var result = _primeService.IsPrime(value);
Assert.False(result, $"{value} should not be prime");
}
}
テストを実行して、失敗することを確認
dotnet test
Determining projects to restore...
All projects are up-to-date for restore.
PrimeService -> /Users/***/project/csharp/dotnet_core_xunit/unit-testing-using-dotnet-test/PrimeService/bin/Debug/net6.0/PrimeService.dll
PrimeService.Tests -> /Users/***/project/csharp/dotnet_core_xunit/unit-testing-using-dotnet-test/PrimeService.Tests/bin/Debug/net6.0/PrimeService.Tests.dll
Test run for /Users/***/project/csharp/dotnet_core_xunit/unit-testing-using-dotnet-test/PrimeService.Tests/bin/Debug/net6.0/PrimeService.Tests.dll (.NETCoreApp,Version=v6.0)
Microsoft (R) Test Execution Command Line Tool Version 17.3.1 (x64)
Copyright (c) Microsoft Corporation. All rights reserved.
Starting test execution, please wait...
A total of 1 test files matched the specified pattern.
[xUnit.net 00:00:00.67] Prime.UnitTests.Services.PrimeService_IsPrimeShould.IsPrime_ValuesLessThan2_ReturnFalse(value: 0) [FAIL]
[xUnit.net 00:00:00.67] Prime.UnitTests.Services.PrimeService_IsPrimeShould.IsPrime_ValuesLessThan2_ReturnFalse(value: -1) [FAIL]
Failed Prime.UnitTests.Services.PrimeService_IsPrimeShould.IsPrime_ValuesLessThan2_ReturnFalse(value: 0) [< 1 ms]
Error Message:
System.NotImplementedException : Not fully implemented.
Stack Trace:
at Prime.Services.PrimeService.IsPrime(Int32 candidate) in /Users/***/project/csharp/dotnet_core_xunit/unit-testing-using-dotnet-test/PrimeService/PrimeService.cs:line 13
at Prime.UnitTests.Services.PrimeService_IsPrimeShould.IsPrime_ValuesLessThan2_ReturnFalse(Int32 value) in /Users/***/project/csharp/dotnet_core_xunit/unit-testing-using-dotnet-test/PrimeService.Tests/PrimeService_IsPrimeShould.cs:line 21
Failed Prime.UnitTests.Services.PrimeService_IsPrimeShould.IsPrime_ValuesLessThan2_ReturnFalse(value: -1) [< 1 ms]
Error Message:
System.NotImplementedException : Not fully implemented.
Stack Trace:
at Prime.Services.PrimeService.IsPrime(Int32 candidate) in /Users/***/project/csharp/dotnet_core_xunit/unit-testing-using-dotnet-test/PrimeService/PrimeService.cs:line 13
at Prime.UnitTests.Services.PrimeService_IsPrimeShould.IsPrime_ValuesLessThan2_ReturnFalse(Int32 value) in /Users/***/project/csharp/dotnet_core_xunit/unit-testing-using-dotnet-test/PrimeService.Tests/PrimeService_IsPrimeShould.cs:line 21
Failed! - Failed: 2, Passed: 1, Skipped: 0, Total: 3, Duration: 25 ms - /Users/tetsu/project/csharp/dotnet_core_xunit/unit-testing-using-dotnet-test/PrimeService.Tests/bin/Debug/net6.0/PrimeService.Tests.dll (net6.0)
テストが合格するようにPrimeService/PrimeService.cs
のIsPrime
メソッドを更新
public bool IsPrime(int candidate)
{
if (candidate < 2)
{
return false;
}
throw new NotImplementedException("Not fully implemented.");
}
テストランナーを実行して、テストの合格を確認
dotnet test
Determining projects to restore...
All projects are up-to-date for restore.
PrimeService -> /Users/***/project/csharp/dotnet_core_xunit/unit-testing-using-dotnet-test/PrimeService/bin/Debug/net6.0/PrimeService.dll
PrimeService.Tests -> /Users/***/project/csharp/dotnet_core_xunit/unit-testing-using-dotnet-test/PrimeService.Tests/bin/Debug/net6.0/PrimeService.Tests.dll
Test run for /Users/***/project/csharp/dotnet_core_xunit/unit-testing-using-dotnet-test/PrimeService.Tests/bin/Debug/net6.0/PrimeService.Tests.dll (.NETCoreApp,Version=v6.0)
Microsoft (R) Test Execution Command Line Tool Version 17.3.1 (x64)
Copyright (c) Microsoft Corporation. All rights reserved.
Starting test execution, please wait...
A total of 1 test files matched the specified pattern.
Passed! - Failed: 0, Passed: 3, Skipped: 0, Total: 3, Duration: 4 ms - /Users/***/project/csharp/dotnet_core_xunit/unit-testing-using-dotnet-test/PrimeService.Tests/bin/Debug/net6.0/PrimeService.Tests.dll (net6.0)
Reference
dotnet テストと xUnit を使用した .NET Core での単体テスト C#
dotnet add reference
dotnet test
xUnit
dotnet/sample
PrimeServie