TDDBC Sendai X Online の課題をC#でやってみる
いちごの格付け
お題
TDDBC Sendai X Online お題
今回のお題について
いちごは、種の段階から品種が決まっており、成長するとサイズが大きくなり、赤く色づいてくると出荷できるようになります。
農家さんは、出荷する際、できるだけ大きくて見栄えの良いいちごを選びます。見栄えによって出荷時の値段が変わってくるからです。
GitHub
masaru-b-cl/TddbcSendaiXByCSharp: TDDBC Sendai X Online のお題をC#でやってみた
課題1: いちごの作成
お題
いちごを出荷するには、品種とサイズを知る必要があります。
品種とサイズを与えて、いちごを作成し、その文字列表現を取得しましょう。
文字列表現の例: あまおう: S
とちおとめ: M
もういっこ: L
なお、品種は、 あまおう
とちおとめ
もういっこ
の3種類、いちごのサイズは S
M
L
LL
の4種類です。
TODOリストの作成
まず、下記の文の太字部分に着目しましょう。
品種とサイズを与えて、いちごを作成し、その文字列表現を取得しましょう。
「品種」と「サイズ」という言葉が出ましたね。また「作成」とありますので、まずはこの部分だけを切り出して、TODOリストに追加します。
- [ ] 品種とサイズを与えて、いちごを作成する
次に、先程の文の後半に着目しましょう。
品種とサイズを与えて、いちごを作成し、その文字列表現を取得しましょう。
「その」は「いちごの」と置き換えられます。そして「文字列表現を取得」するためには「文字列表現に変換」できないといけないということなので、次のようにTODOリストに付け加えます。
- [ ] 品種とサイズを与えて、いちごを作成する
- [ ] いちごを文字列表現に変換する
次に、下記の部分に着目します。
文字列表現の例:
あまおう: S
とちおとめ: M
もういっこ: L
この箇所により、文字列表現の形式が<品種>: <サイズ>
であることがわかります。こちらを「いちごを文字列表現に変換する」の項目の下に具体例とともにぶら下げます。
- [ ] 品種とサイズを与えて、いちごを作成する
- [ ] いちごを文字列表現に変換する
- [ ] "<品種>: <サイズ>"形式になる
- [ ] 「あまおう」の「S」サイズは"あまおう: S"になる
今度は最後の文に着目します。
なお、品種は、
あまおう
とちおとめ
もういっこ
の3種類、いちごのサイズはS
M
L
LL
の4種類です。
この文により「品種」、「サイズ」に与えることが可能な値の範囲が分かりますので、それぞれTODOリストに追加します。
- [ ] 品種とサイズを与えて、いちごを作成する
- [ ] いちごの品種
- [ ] あまおう
- [ ] とちおとめ
- [ ] もういっこ
- [ ] いちごのサイズ
- [ ] S
- [ ] M
- [ ] L
- [ ] LL
- [ ] いちごを文字列表現に変換する
- [ ] "<品種>: <サイズ>"形式になる
- [ ] 「あまおう」の「S」サイズは"あまおう: S"になる
ただし、提示された値以外を与えたらどうなるか、仕様には明記されていません。例えばnullや空文字などです。
こういった場合は、仕様策定者に確認をしましょう。その結果、ここでは無効な引数であるとして、例外を発生させることになりました。これもTODOリストに追加します。
- [ ] 品種とサイズを与えて、いちごを作成する
- [ ] いちごの品種
- [ ] あまおう
- [ ] とちおとめ
- [ ] もういっこ
- [ ] 想定外の値は例外を発生させる
- [ ] いちごのサイズ
- [ ] S
- [ ] M
- [ ] L
- [ ] LL
- [ ] 想定外の値は例外を発生させる
- [ ] いちごを文字列表現に変換する
- [ ] "<品種>: <サイズ>"形式になる
- [ ] 「あまおう」の「S」サイズは"あまおう: S"になる
これで、一旦TODOリストを完成とします。
最初のテストを書くその前に
それではいよいよコードを書き始めましょう。まずは、最初のテストを書くことを目標に始めます。
が、「最初のテストを書く」といっても、実はその前にやることがたくさんあります。順に見ていきましょう。
プロダクトの名付け
まず、そもそもこのプロダクトの名前を決めるところから始めないといけません。今回のお題は「いちごの格付け」です。「いちご」は英語でStrawberry
ですが、長くてタイプしにくいですし、単にIchigo
にしてしまいましょう。そして「格付け」の部分は「ランクを計算する」とみなし、Rank
、Calculator
という言葉を使うことにして、今回はIchigoRankCalculator
にしましょう。
ワークスペース作成
次に、コードのワークスペースを作成します。今回はC#ですので、.NET SDKのdotnet
cliを使いましょう。
dotnet
cliでは、何かを新たに作成するためにnew
コマンドを使います。何も指定せずに実行すると、作成できるものの一覧が表示されます。
$ dotnet new
Templates Short Name Language Tags
-------------------------------------------- -------------- ---------- ----------------------
Console Application console [C#],F#,VB Common/Console
Class library classlib [C#],F#,VB Common/Library
Worker Service worker [C#],F# Common/Worker/Web
Unit Test Project mstest [C#],F#,VB Test/MSTest
NUnit 3 Test Project nunit [C#],F#,VB Test/NUnit
NUnit 3 Test Item nunit-test [C#],F#,VB Test/NUnit
xUnit Test Project xunit [C#],F#,VB Test/xUnit
Razor Component razorcomponent [C#] Web/ASP.NET
Razor Page page [C#] Web/ASP.NET
MVC ViewImports viewimports [C#] Web/ASP.NET
MVC ViewStart viewstart [C#] Web/ASP.NET
Blazor Server App blazorserver [C#] Web/Blazor
Blazor WebAssembly App blazorwasm [C#] Web/Blazor/WebAssembly
ASP.NET Core Empty web [C#],F# Web/Empty
ASP.NET Core Web App (Model-View-Controller) mvc [C#],F# Web/MVC
ASP.NET Core Web App webapp [C#] Web/MVC/Razor Pages
ASP.NET Core with Angular angular [C#] Web/MVC/SPA
ASP.NET Core with React.js react [C#] Web/MVC/SPA
ASP.NET Core with React.js and Redux reactredux [C#] Web/MVC/SPA
Razor Class Library razorclasslib [C#] Web/Razor/Library
ASP.NET Core Web API webapi [C#],F# Web/WebAPI
ASP.NET Core gRPC Service grpc [C#] Web/gRPC
dotnet gitignore file gitignore Config
global.json file globaljson Config
NuGet Config nugetconfig Config
Dotnet local tool manifest file tool-manifest Config
Web Config webconfig Config
Solution File sln Solution
Protocol Buffer File proto Web/gRPC
Examples:
dotnet new mvc --auth Individual
dotnet new react --auth Individual
dotnet new --help
dotnet new gitignore --help
まずはソリューションの作成です。上記の出力結果を見ると、テンプレートに「Solution File」というものがあります。
Solution File sln Solution
よって、その「Short Name」であるsln
を指定して実行します。
$ dotnet new sln -o IchigoRankCalculator
The template "Solution File" was created successfully.
コマンドを実行すると、次のようにディレクトリとslnファイルが作成されます。
$ tree IchigoRankCalculator
IchigoRankCalculator
└── IchigoRankCalculator.sln
0 directories, 1 file
以降の作業は作成したソリューションディレクトリに移動して続けましょう。
$ cd IchigoRankCalculator
テストプロジェクト作成
次に、テストプロジェクトを作成しましょう。今回はテスティングフレームワークにxUnit.netを用います。
先程見たdotnet new
コマンドのテンプレート一覧を見ると、xUnitを使ったテストプロジェクトはxunit
コマンドで作成できることがわかります。
xUnit Test Project xunit [C#],F#,VB Test/xUnit
C#のコードでは、テストプロジェクトは<プロダクト名>.Test
形式で名付けられることが多いので、ここでもそれに倣ってIchigoRankCalculator.Test
という名前で作成しましょう。
$ dotnet new xunit -o IchigoRankCalculator.Test
The template "xUnit Test Project" was created successfully.
Processing post-creation actions...
Running 'dotnet restore' on IchigoRankCalculator.Test/IchigoRankCalculator.Test.csproj...
復元対象のプロジェクトを決定しています...
/Users/takano.sho/dotnetproj/TddbcSendaiXByCSharp/IchigoRankCalculator/IchigoRankCalculator.Test/IchigoRankCalculator.Test.csproj を復元しました (957 ms)。
Restore succeeded.
$ tree .
.
├── IchigoRankCalculator.Test
│ ├── IchigoRankCalculator.Test.csproj
│ ├── UnitTest1.cs
│ └── obj
│ ├── IchigoRankCalculator.Test.csproj.nuget.dgspec.json
│ ├── IchigoRankCalculator.Test.csproj.nuget.g.props
│ ├── IchigoRankCalculator.Test.csproj.nuget.g.targets
│ ├── project.assets.json
│ └── project.nuget.cache
└── IchigoRankCalculator.sln
作成したテストプロジェクトは、dotnet sln add
コマンドでソリューションに追加しておきます。
$ dotnet sln add IchigoRankCalculator.Test
プロジェクト `IchigoRankCalculator.Test/IchigoRankCalculator.Test.csproj` をソリューションに追加しました。
ここまででテストプロジェクトの作成がうまくできているか確認するため、一度テストを実行しておきましょう。
テストを実行するには、dotnet test
コマンドを実行します。
$ dotnet test
復元対象のプロジェクトを決定しています...
復元対象のすべてのプロジェクトは最新です。
IchigoRankCalculator.Test -> /Users/takano.sho/dotnetproj/TddbcSendaiXByCSharp/IchigoRankCalculator/IchigoRankCalculator.Test/bin/Debug/net5.0/IchigoRankCalculator.Test.dll
/Users/takano.sho/dotnetproj/TddbcSendaiXByCSharp/IchigoRankCalculator/IchigoRankCalculator.Test/bin/Debug/net5.0/IchigoRankCalculator.Test.dll (.NETCoreApp,Version=v5.0) のテスト実行
Microsoft (R) Test Execution Command Line Tool Version 16.9.0
Copyright (c) Microsoft Corporation. All rights reserved.
テスト実行を開始しています。お待ちください...
合計 1 個のテスト ファイルが指定されたパターンと一致しました。
成功! -失敗: 0、合格: 1、スキップ: 0、合計: 1、期間: 2 ms - /Users/takano.sho/dotnetproj/TddbcSendaiXByCSharp/IchigoRankCalculator/IchigoRankCalculator.Test/bin/Debug/net5.0/IchigoRankCalculator.Test.dll (net5.0)
無事、テストが実行できることを確認しました。
クラスライブラリプロジェクト作成
テストが実行できたところで、いよいよプロダクトコードを書くためのクラスライブラリプロジェクトを作成します。
なお、.NETのプログラムでは、実行形式であるアプリプロジェクトを対象にテストを書くことも可能です。しかし、あくまでテスト対象はライブラリとして作成し、アプリプロジェクトではこのライブラリを参照して実行するような形にしたほうが良いでしょう。
クラスライブラリプロジェクトを作成するには、dotnet new
コマンドにclasslib
を指定します。
Class library classlib [C#],F#,VB Common/Library
$ dotnet new classlib -o IchigoRankCalculator
The template "Class library" was created successfully.
Processing post-creation actions...
Running 'dotnet restore' on IchigoRankCalculator/IchigoRankCalculator.csproj...
復元対象のプロジェクトを決定しています...
/Users/takano.sho/dotnetproj/TddbcSendaiXByCSharp/IchigoRankCalculator/IchigoRankCalculator/IchigoRankCalculator.csproj を復元しました (60 ms)。
Restore succeeded.
先程のテストプロジェクトと同様にソリューションに追加しておきます。
$ dotnet sln add IchigoRankCalculator
プロジェクト `IchigoRankCalculator/IchigoRankCalculator.csproj` をソリューションに追加しました。
また、テストプロジェクトに対しても、クラスライブラリプロジェクトへの参照を追加しておきましょう。これには、dotnet add <テストプロジェクト> reference <クラスライブラリプロジェクト>
コマンドを使います。
$ dotnet add IchigoRankCalculator.Test reference IchigoRankCalculator
参照 `..\IchigoRankCalculator\IchigoRankCalculator.csproj` がプロジェクトに追加されました。
これでようやく最初のテストを書く準備ができました。
$ tree .
.
├── IchigoRankCalculator
│ ├── Class1.cs
│ ├── IchigoRankCalculator.csproj
│ └── obj
│ ├── IchigoRankCalculator.csproj.nuget.dgspec.json
│ ├── IchigoRankCalculator.csproj.nuget.g.props
│ ├── IchigoRankCalculator.csproj.nuget.g.targets
│ ├── project.assets.json
│ └── project.nuget.cache
├── IchigoRankCalculator.Test
│ ├── IchigoRankCalculator.Test.csproj
│ ├── UnitTest1.cs
│ └── obj
│ ├── IchigoRankCalculator.Test.csproj.nuget.dgspec.json
│ ├── IchigoRankCalculator.Test.csproj.nuget.g.props
│ ├── IchigoRankCalculator.Test.csproj.nuget.g.targets
│ ├── project.assets.json
│ └── project.nuget.cache
└── IchigoRankCalculator.sln
最初のテストを作成する
準備が整ったところで最初のテストを書いていきましょう。
取り組むTODOの選択
まずは作成したTODOリストから、最初に手を付けるべき項目を考えます。
一番やりやすいのは次の項目です。
- [ ] 品種とサイズを与えて、いちごを作成する
ただ、このままではまだコードを書くには曖昧すぎることがわかります。「品種」と「サイズ」をどういう形式で扱うのかをまだ決めていなかったためです。
そこで、ここでは1番かんたんな「文字列」として、品種とサイズを扱うことにしましょう。ですので、最初に作成するテストのために、次のようにサブタスクを追加します。
- [ ] 品種とサイズを与えて、いちごを作成する
- [ ] 品種に"あまおう"、サイズに"S"を与えて、いちごを作成する
最初のテストコード
追加したTODOを元に、最初のテストコードを作成します。
先程テストプロジェクトを生成した際、UnitTest1.cs
というファイルが既に作成されています。
using System;
using Xunit;
namespace IchigoRankCalculator.Test
{
public class UnitTest1
{
[Fact]
public void Test1()
{
}
}
}
まずは、このファイルの名前を変えましょう。今回は単純にIchigoRankCalculatorTest.cs
とでもしておきましょう。
$ mv IchigoRankCalculator.Test/UnitTest1.cs IchigoRankCalculator.Test/IchigoRankCalculatorTest.cs
次にテストクラス名を変更します。C#はクラス名に日本語が使えるので、とりあえず「いちごの作成」と名前をつけます。
using System;
using Xunit;
namespace IchigoRankCalculator.Test
{
public class いちごの作成
{
[Fact]
public void Test1()
{
}
}
}
次に、最初に選んだTODOをもとにテストメソッド名をつけます。
using System;
using Xunit;
namespace IchigoRankCalculator.Test
{
public class いちごの作成
{
[Fact]
public void 品種にあまおう_サイズにSを与えていちごを作成する()
{
}
}
}
TDDはアサートファーストが原則なので、アサーションから書いていきます。
using System;
using Xunit;
namespace IchigoRankCalculator.Test
{
public class いちごの作成
{
[Fact]
public void 品種にあまおう_サイズにSを与えていちごを作成する()
{
Assert.NotNull(ichigo);
}
}
}
ichigo
はIchigo
型のクラスのインスタンスであるとして、new
演算子で作成しましょう。
using System;
using Xunit;
namespace IchigoRankCalculator.Test
{
public class いちごの作成
{
[Fact]
public void 品種にあまおう_サイズにSを与えていちごを作成する()
{
Assert.NotNull(ichigo);
}
}
}
ただ、このままではIchigo
クラスがありませんのでコンパイルエラーのままです。そこで、クラスライブラリプロジェクト内に生成されたClass1.cs
ファイル
using System;
namespace IchigoRankCalculator
{
public class Class1
{
}
}
をIchigo.cs
にリネームし、クラス名もClass1
からIchigo
に変更しましょう。
using System;
namespace IchigoRankCalculator
{
public class Ichigo
{
}
}
そして、dotnet test
コマンドを使ってテストを実行して、無事成功しました。
復元対象のプロジェクトを決定しています...
復元対象のすべてのプロジェクトは最新です。
IchigoRankCalculator -> /Users/takano.sho/dotnetproj/TddbcSendaiXByCSharp/IchigoRankCalculator/IchigoRankCalculator/bin/Debug/net5.0/IchigoRankCalculator.dll
IchigoRankCalculator.Test -> /Users/takano.sho/dotnetproj/TddbcSendaiXByCSharp/IchigoRankCalculator/IchigoRankCalculator.Test/bin/Debug/net5.0/IchigoRankCalculator.Test.dll
/Users/takano.sho/dotnetproj/TddbcSendaiXByCSharp/IchigoRankCalculator/IchigoRankCalculator.Test/bin/Debug/net5.0/IchigoRankCalculator.Test.dll (.NETCoreApp,Version=v5.0) のテスト実行
Microsoft (R) Test Execution Command Line Tool Version 16.9.0
Copyright (c) Microsoft Corporation. All rights reserved.
テスト実行を開始しています。お待ちください...
合計 1 個のテスト ファイルが指定されたパターンと一致しました。
成功! -失敗: 0、合格: 1、スキップ: 0、合計: 1、期間: 2 ms - /Users/takano.sho/dotnetproj/TddbcSendaiXByCSharp/IchigoRankCalculator/IchigoRankCalculator.Test/bin/Debug/net5.0/IchigoRankCalculator.Test.dll (net5.0)
品種とサイズを与えて、いちごを作成する
いちごが作成できるようになったので、次は「品種」と「サイズ」を与えて作成できるようにしましょう。
コードを修正する前に、「品種」をコード上なんと表現するか考えないといけません。
英辞郎 on the WEBで「品種」を検索すると「breed」という単語が出てきます。
breedの意味・使い方・読み方|英辞郎 on the WEB
名
- 《生物》〔動植物の〕種族、品種◆人間が交配して作る種を指すことが多い。
そこで、今回は「品種」は「breed」という単語で表すことにしましょう。
TDDですので、まずはテストを変更します。
using System;
using Xunit;
namespace IchigoRankCalculator.Test
{
public class いちごの作成
{
[Fact]
public void 品種にあまおう_サイズにSを与えていちごを作成する()
{
Ichigo ichigo = new Ichigo(breed: "あまおう", size: "S");
// Assert.NotNull(ichigo);
Assert.Equal("あまおう", ichigo.Breed);
Assert.Equal("S", ichigo.Size);
}
}
}
このテストが通るように、プロダクトコードを修正します。まず、「仮実装」でやっていきます。
using System;
namespace IchigoRankCalculator
{
public class Ichigo
{
public Ichigo(string breed, string size)
{
}
public string Breed => "あまおう";
public string Size => "S";
}
}
テストが通ることを確認しましょう。
$ dotnet test IchigoRankCalculator/IchigoRankCalculator.sln
復元対象のプロジェクトを決定しています...
復元対象のすべてのプロジェクトは最新です。
IchigoRankCalculator -> /Users/takano.sho/dotnetproj/TddbcSendaiXByCSharp/IchigoRankCalculator/IchigoRankCalculator/bin/Debug/net5.0/IchigoRankCalculator.dll
IchigoRankCalculator.Test -> /Users/takano.sho/dotnetproj/TddbcSendaiXByCSharp/IchigoRankCalculator/IchigoRankCalculator.Test/bin/Debug/net5.0/IchigoRankCalculator.Test.dll
/Users/takano.sho/dotnetproj/TddbcSendaiXByCSharp/IchigoRankCalculator/IchigoRankCalculator.Test/bin/Debug/net5.0/IchigoRankCalculator.Test.dll (.NETCoreApp,Version=v5.0) のテスト実行
Microsoft (R) Test Execution Command Line Tool Version 16.9.0
Copyright (c) Microsoft Corporation. All rights reserved.
テスト実行を開始しています。お待ちください...
合計 1 個のテスト ファイルが指定されたパターンと一致しました。
成功! -失敗: 0、合格: 1、スキップ: 0、合計: 1、期間: 2 ms - /Users/takano.sho/dotnetproj/TddbcSendaiXByCSharp/IchigoRankCalculator/IchigoRankCalculator.Test/bin/Debug/net5.0/IchigoRankCalculator.Test.dll (net5.0)
続いて、仮実装を本実装を進めるため、もう一つテストを追加し、三角測量を行います。
using System;
using Xunit;
namespace IchigoRankCalculator.Test
{
public class いちごの作成
{
[Fact]
public void 品種にあまおう_サイズにSを与えていちごを作成する()
{
Ichigo ichigo = new Ichigo(breed: "あまおう", size: "S");
// Assert.NotNull(ichigo);
Assert.Equal("あまおう", ichigo.Breed);
Assert.Equal("S", ichigo.Size);
}
// ↓追加したテスト
[Fact]
public void 品種にとちおとめ_サイズにMを与えていちごを作成する()
{
Ichigo ichigo = new Ichigo(breed: "とちおとめ", size: "M");
// Assert.NotNull(ichigo);
Assert.Equal("とちおとめ", ichigo.Breed);
Assert.Equal("M", ichigo.Size);
}
}
}
テストを実行し、追加したテストが「想定通りに失敗すること」を確認します。
$ dotnet test IchigoRankCalculator/IchigoRankCalculator.sln
復元対象のプロジェクトを決定しています...
復元対象のすべてのプロジェクトは最新です。
IchigoRankCalculator -> /Users/takano.sho/dotnetproj/TddbcSendaiXByCSharp/IchigoRankCalculator/IchigoRankCalculator/bin/Debug/net5.0/IchigoRankCalculator.dll
IchigoRankCalculator.Test -> /Users/takano.sho/dotnetproj/TddbcSendaiXByCSharp/IchigoRankCalculator/IchigoRankCalculator.Test/bin/Debug/net5.0/IchigoRankCalculator.Test.dll
/Users/takano.sho/dotnetproj/TddbcSendaiXByCSharp/IchigoRankCalculator/IchigoRankCalculator.Test/bin/Debug/net5.0/IchigoRankCalculator.Test.dll (.NETCoreApp,Version=v5.0) のテスト実行
Microsoft (R) Test Execution Command Line Tool Version 16.9.0
Copyright (c) Microsoft Corporation. All rights reserved.
テスト実行を開始しています。お待ちください...
合計 1 個のテスト ファイルが指定されたパターンと一致しました。
[xUnit.net 00:00:00.66] IchigoRankCalculator.Test.いちごの作成.品種にとちおとめ_サイズにMを与えていちごを作成する [FAIL]
失敗 IchigoRankCalculator.Test.いちごの作成.品種にとちおとめ_サイズにMを与えていちごを作成する [3 ms]
エラー メッセージ:
Assert.Equal() Failure
↓ (pos 0)
Expected: とちおとめ
Actual: あまおう
↑ (pos 0)
スタック トレース:
at IchigoRankCalculator.Test.いちごの作成.品種にとちおとめ_サイズにMを与えていちごを作成する() in /Users/takano.sho/dotnetproj/TddbcSendaiXByCSharp/IchigoRankCalculator/IchigoRankCalculator.Test/IchigoRankCalculatorTest.cs:line 24
失敗! -失敗: 1、合格: 1、スキップ: 0、合計: 2、期間: 4 ms - /Users/takano.sho/dotnetproj/TddbcSendaiXByCSharp/IchigoRankCalculator/IchigoRankCalculator.Test/bin/Debug/net5.0/IchigoRankCalculator.Test.dll (net5.0)
この失敗を成功させるよう、本実装を行います。Breed
、Size
をget
飲み可能なプロパティにして、コンストラクタ引数の値をセットするように変更します。
using System;
namespace IchigoRankCalculator
{
public class Ichigo
{
public Ichigo(string breed, string size)
{
this.Breed = breed;
this.Size = size;
}
public string Breed { get; }
public string Size { get; }
}
}
そして、テストを実行して問題ないことを確認します。
$ dotnet test IchigoRankCalculator/IchigoRankCalculator.sln
復元対象のプロジェクトを決定しています...
復元対象のすべてのプロジェクトは最新です。
IchigoRankCalculator -> /Users/takano.sho/dotnetproj/TddbcSendaiXByCSharp/IchigoRankCalculator/IchigoRankCalculator/bin/Debug/net5.0/IchigoRankCalculator.dll
IchigoRankCalculator.Test -> /Users/takano.sho/dotnetproj/TddbcSendaiXByCSharp/IchigoRankCalculator/IchigoRankCalculator.Test/bin/Debug/net5.0/IchigoRankCalculator.Test.dll
/Users/takano.sho/dotnetproj/TddbcSendaiXByCSharp/IchigoRankCalculator/IchigoRankCalculator.Test/bin/Debug/net5.0/IchigoRankCalculator.Test.dll (.NETCoreApp,Version=v5.0) のテスト実行
Microsoft (R) Test Execution Command Line Tool Version 16.9.0
Copyright (c) Microsoft Corporation. All rights reserved.
テスト実行を開始しています。お待ちください...
合計 1 個のテスト ファイルが指定されたパターンと一致しました。
成功! -失敗: 0、合格: 2、スキップ: 0、合計: 2、期間: 3 ms - /Users/takano.sho/dotnetproj/TddbcSendaiXByCSharp/IchigoRankCalculator/IchigoRankCalculator.Test/bin/Debug/net5.0/IchigoRankCalculator.Test.dll (net5.0)
テストが成功したところで、テストコードのリファクタリングを行います。といっても、ここでは不要になったコメントアウトされたアサーションを削除するくらいにとどめておきましょう。
using System;
using Xunit;
namespace IchigoRankCalculator.Test
{
public class いちごの作成
{
[Fact]
public void 品種にあまおう_サイズにSを与えていちごを作成する()
{
Ichigo ichigo = new Ichigo(breed: "あまおう", size: "S");
Assert.Equal("あまおう", ichigo.Breed);
Assert.Equal("S", ichigo.Size);
}
[Fact]
public void 品種にとちおとめ_サイズにMを与えていちごを作成する()
{
Ichigo ichigo = new Ichigo(breed: "とちおとめ", size: "M");
Assert.Equal("とちおとめ", ichigo.Breed);
Assert.Equal("M", ichigo.Size);
}
}
}
ここまでで完了したTODOを反映しておきます。
- [ ] 品種とサイズを与えて、いちごを作成する
- [x] ~~品種に"あまおう"、サイズに"S"を与えて、いちごを作成する~~
- [ ] いちごの品種
- [x] あまおう
- [ ] とちおとめ
- [ ] もういっこ
- [ ] 想定外の値は例外を発生させる
- [ ] いちごのサイズ
- [x] S
- [x] M
- [ ] L
- [ ] LL
- [ ] 想定外の値は例外を発生させる
- [ ] いちごを文字列表現に変換する
- [ ] "<品種>: <サイズ>"形式になる
- [ ] 「あまおう」の「S」サイズは"あまおう: S"になる
いちごを文字列表現に変換する
次は
- [ ] いちごを文字列表現に変換する
- [ ] "<品種>: <サイズ>"形式になる
- [ ] 「あまおう」の「S」サイズは"あまおう: S"になる
のTODOに取り組んでいきましょう。
最初はテストからです。これまで作成した2つのテストとは別に作成しましょう。
public class いちごを文字列表現に変換する
{
[Fact(DisplayName = "あまおうのSサイズは\"あまおう: S\"になる")]
public void あまおうのSサイズ()
{
var ichigo = new Ichigo(breed: "あまおう", size: "S");
Assert.Equal("あまおう: S", ichigo.ToString());
}
}
まず、先程とは別観点のテストなので、テストクラスも新たに作成します。
次に、テストメソッドを追加しますが、今回のテストは期待値として「"あまおう: S"」があるので、テストメソッドでもそれを表現したいです。そんなとき、xUnit.netでは、Fact
属性のDisplayName
引数でテストの表示名を指定できますので、それを利用します。
そして、「いちごを文字列表現に変換する」のですから、とりあえず最もシンプルなToString()
メソッドを使って変換させることにしましょう。
テストを実行して、失敗することを確認します。
$ dotnet test IchigoRankCalculator/IchigoRankCalculator.sln
復元対象のプロジェクトを決定しています...
復元対象のすべてのプロジェクトは最新です。
IchigoRankCalculator -> /Users/takano.sho/dotnetproj/TddbcSendaiXByCSharp/IchigoRankCalculator/IchigoRankCalculator/bin/Debug/net5.0/IchigoRankCalculator.dll
IchigoRankCalculator.Test -> /Users/takano.sho/dotnetproj/TddbcSendaiXByCSharp/IchigoRankCalculator/IchigoRankCalculator.Test/bin/Debug/net5.0/IchigoRankCalculator.Test.dll
/Users/takano.sho/dotnetproj/TddbcSendaiXByCSharp/IchigoRankCalculator/IchigoRankCalculator.Test/bin/Debug/net5.0/IchigoRankCalculator.Test.dll (.NETCoreApp,Version=v5.0) のテスト実行
Microsoft (R) Test Execution Command Line Tool Version 16.9.0
Copyright (c) Microsoft Corporation. All rights reserved.
テスト実行を開始しています。お待ちください...
合計 1 個のテスト ファイルが指定されたパターンと一致しました。
[xUnit.net 00:00:00.52] あまおうのSサイズは"あまおう: S"になる [FAIL]
失敗 あまおうのSサイズは"あまおう: S"になる [3 ms]
エラー メッセージ:
Assert.Equal() Failure
↓ (pos 0)
Expected: あまおう: S
Actual: IchigoRankCalculator.Ichigo
↑ (pos 0)
スタック トレース:
at IchigoRankCalculator.Test.いちごを文字列表現に変換する.あまおうのSサイズ() in /Users/takano.sho/dotnetproj/TddbcSendaiXByCSharp/IchigoRankCalculator/IchigoRankCalculator.Test/IchigoRankCalculatorTest.cs:line 33
失敗! -失敗: 1、合格: 2、スキップ: 0、合計: 3、期間: 6 ms - /Users/takano.sho/dotnetproj/TddbcSendaiXByCSharp/IchigoRankCalculator/IchigoRankCalculator.Test/bin/Debug/net5.0/IchigoRankCalculator.Test.dll (net5.0)
想定通り失敗し、テスト名にもFact
属性のDisplayName
引数で指定した「あまおうのSサイズは"あまおう: S"になる」が表示されているのを確認できます。
このテストを通すように、まずは仮実装です。ToString()
メソッドをオーバーライドして、リテラル文字列"あまおう: S"を返すようにしましょう。
using System;
namespace IchigoRankCalculator
{
public class Ichigo
{
public Ichigo(string breed, string size)
{
Breed = breed;
Size = size;
}
public string Breed { get; }
public string Size { get; }
public override string ToString()
{
return "あまおう: S";
}
}
}
テストを実行して成功することを確認します。
$ dotnet test IchigoRankCalculator/IchigoRankCalculator.sln
復元対象のプロジェクトを決定しています...
復元対象のすべてのプロジェクトは最新です。
IchigoRankCalculator -> /Users/takano.sho/dotnetproj/TddbcSendaiXByCSharp/IchigoRankCalculator/IchigoRankCalculator/bin/Debug/net5.0/IchigoRankCalculator.dll
IchigoRankCalculator.Test -> /Users/takano.sho/dotnetproj/TddbcSendaiXByCSharp/IchigoRankCalculator/IchigoRankCalculator.Test/bin/Debug/net5.0/IchigoRankCalculator.Test.dll
/Users/takano.sho/dotnetproj/TddbcSendaiXByCSharp/IchigoRankCalculator/IchigoRankCalculator.Test/bin/Debug/net5.0/IchigoRankCalculator.Test.dll (.NETCoreApp,Version=v5.0) のテスト実行
Microsoft (R) Test Execution Command Line Tool Version 16.9.0
Copyright (c) Microsoft Corporation. All rights reserved.
テスト実行を開始しています。お待ちください...
合計 1 個のテスト ファイルが指定されたパターンと一致しました。
成功! -失敗: 0、合格: 3、スキップ: 0、合計: 3、期間: 6 ms - /Users/takano.sho/dotnetproj/TddbcSendaiXByCSharp/IchigoRankCalculator/IchigoRankCalculator.Test/bin/Debug/net5.0/IchigoRankCalculator.Test.dll (net5.0)
今度はテストが通るまま、本実装を進めていきましょう。まずはいちごの「品種」を埋め込んでみましょう。$"〜"
を用いた「文字列補間(string interpolation)」を使ってやっていきます。
public override string ToString()
{
return $"{Breed}: S";
}
テストを実行し、通ったままなことを確認します。
$ dotnet test IchigoRankCalculator/IchigoRankCalculator.sln
復元対象のプロジェクトを決定しています...
復元対象のすべてのプロジェクトは最新です。
IchigoRankCalculator -> /Users/takano.sho/dotnetproj/TddbcSendaiXByCSharp/IchigoRankCalculator/IchigoRankCalculator/bin/Debug/net5.0/IchigoRankCalculator.dll
IchigoRankCalculator.Test -> /Users/takano.sho/dotnetproj/TddbcSendaiXByCSharp/IchigoRankCalculator/IchigoRankCalculator.Test/bin/Debug/net5.0/IchigoRankCalculator.Test.dll
/Users/takano.sho/dotnetproj/TddbcSendaiXByCSharp/IchigoRankCalculator/IchigoRankCalculator.Test/bin/Debug/net5.0/IchigoRankCalculator.Test.dll (.NETCoreApp,Version=v5.0) のテスト実行
Microsoft (R) Test Execution Command Line Tool Version 16.9.0
Copyright (c) Microsoft Corporation. All rights reserved.
テスト実行を開始しています。お待ちください...
合計 1 個のテスト ファイルが指定されたパターンと一致しました。
成功! -失敗: 0、合格: 3、スキップ: 0、合計: 3、期間: 6 ms - /Users/takano.sho/dotnetproj/TddbcSendaiXByCSharp/IchigoRankCalculator/IchigoRankCalculator.Test/bin/Debug/net5.0/IchigoRankCalculator.Test.dll (net5.0)
つづいて、今度は「サイズ」を埋め込みましょう。「品種」と同様に対応します。
public override string ToString()
{
return $"{Breed}: {Size}";
}
テストを実行して確認します。
$ dotnet test IchigoRankCalculator/IchigoRankCalculator.sln
復元対象のプロジェクトを決定しています...
復元対象のすべてのプロジェクトは最新です。
IchigoRankCalculator -> /Users/takano.sho/dotnetproj/TddbcSendaiXByCSharp/IchigoRankCalculator/IchigoRankCalculator/bin/Debug/net5.0/IchigoRankCalculator.dll
IchigoRankCalculator.Test -> /Users/takano.sho/dotnetproj/TddbcSendaiXByCSharp/IchigoRankCalculator/IchigoRankCalculator.Test/bin/Debug/net5.0/IchigoRankCalculator.Test.dll
/Users/takano.sho/dotnetproj/TddbcSendaiXByCSharp/IchigoRankCalculator/IchigoRankCalculator.Test/bin/Debug/net5.0/IchigoRankCalculator.Test.dll (.NETCoreApp,Version=v5.0) のテスト実行
Microsoft (R) Test Execution Command Line Tool Version 16.9.0
Copyright (c) Microsoft Corporation. All rights reserved.
テスト実行を開始しています。お待ちください...
合計 1 個のテスト ファイルが指定されたパターンと一致しました。
成功! -失敗: 0、合格: 3、スキップ: 0、合計: 3、期間: 6 ms - /Users/takano.sho/dotnetproj/TddbcSendaiXByCSharp/IchigoRankCalculator/IchigoRankCalculator.Test/bin/Debug/net5.0/IchigoRankCalculator.Test.dll (net5.0)
これでTODOを完了にできます。
- [ ] 品種とサイズを与えて、いちごを作成する
- [x] 品種に"あまおう"、サイズに"S"を与えて、いちごを作成する
- [ ] いちごの品種
- [x] あまおう
- [ ] とちおとめ
- [ ] もういっこ
- [ ] 想定外の値は例外を発生させる
- [ ] いちごのサイズ
- [x] S
- [x] M
- [ ] L
- [ ] LL
- [ ] 想定外の値は例外を発生させる
- [x] いちごを文字列表現に変換する
- [x] "<品種>: <サイズ>"形式になる
- [x] 「あまおう」の「S」サイズは"あまおう: S"になる