BEACHSIDE BLOG

MicrosoftとかC#を好むレンジャーの個人的メモ

xUnit 単体テスト 入門 in .NET Core : Assert の基礎

いつも適当に使っている xUnit について整理したいなーと数年思い続け...ついに書く日が来ました。。。

気分次第ですが、複数回に分けて書く予定です。

Overview

準備: VS でプロジェクトの作成

VS 2017 でASP.NET Core の Web のプロジェクトと、xUnit のプロジェクトを作ってみます。 手順は省きますが、「DotnetTestingSamples.NetCoreWeb」と「NetCoreWebTests」の二つのプロジェクトを作りました。

f:id:beachside:20181120160727p:plain


それぞれのプロジェクトに対してパッケージマネージャーコンソールで、

 update-package

をして、Nuget のパッケージを最新にしました。

f:id:beachside:20181120160715p:plain


この時点で、Nugetのバージョンはこんな感じです。特に変哲もないターゲットフレームワーク .NET Core2.1 のアプリですね。

f:id:beachside:20181120160653p:plain

後は、テストプロジェクトから「DotnetTestingSamples.NetCoreWeb」プロジェクトを見えるように参照を追加します。 「NetCoreWebTests」を右クリック > 「追加」 > 「参照」をクリックし、参照マネージャーウインドウを表示させます。 左ペインでプロジェクトをクリックし、「DotnetTestingSamples.NetCoreWeb」にチェックを入れて「OK」ボタンをクリックしましょう。

f:id:beachside:20181120160631p:plain


また、今回多少使うサンプルとして、以下の Person クラスを用意しました。

今回は、以下のよく使いそうな Assert を整理します。

NULL の評価

特に型はこだわらず NULL を評価するには以下のメソッドを使います。NULLについてはもうこれ以上の話はないです。

  • Assert.Null
  • Assert.NotNull

文字列の評価

文字列が同じかを評価する

まずは一番利用する以下のメソッド。

  • Assert.Equal
  • Assert.NotEqual

メソッドの 1st 引数に期待値、2nd 引数に actual な値を入れて評価する基本的な使い方が普通ですね。 文字列を評価する際このメソッドの引数には、3つ目~5つ目にデフォルト値が false に設定されているオプションの引数が存在します。

  • ignoreCase : true に設定すると、大文字小文字が異なっていてもエラーとしない。
  • ignoreLineEndingDifferences : true に設定すると、改行コード(\r\n, \r, \n)が異なる場合でもエラーとしない。
  • ignoreWhiteSpaceDifferences : ture に設定すると、スペースの数やスペースじゃなくてタブでもエラーとしない(スペースがある前提での評価で、スペースがあるものとないものを評価すればエラーになります)。

例えば ignoreCasetrue に設定すれば、(こんなテストが良いかはさておき)大文字が含まれるプロパティに対して、小文字のみの期待値と評価してもがテストはグリーンになります。

文字列が特定の文字列から始まるか / 特定の文字列で終わるか評価する

  • Assert.StartsWith
  • Assert.EndsWith

メソッドの 1st 引数に期待値、2nd 引数に actual な値を入れて評価する単純な方法のほかに、第3引数に StringComparison を付けて評価することができます。StringComparison についての確認は、以下の公式ドキュメントを見るのが良いですね。

文字列に、特定の値が含まれているかを評価する

  • Assert.Contains
  • Assert.DoesNotContain

これも、メソッドの 1st 引数に期待値、2nd 引数に actual な値を入れて評価する単純な方法のほかに、第3引数に StringComparison を付けて評価することができます。


正規表現の評価

以下を使って文字列に対して正規表現の評価ができます。

  • Assert.Matches

特定の値を特定の正規表現で評価する雑なサンプルはこんな感じです。

数値の評価

数値もまずはこのメソッドで評価することが一番多いですね。

  • Assert.Equal
  • Assert.NotEqual

数値の Equal / NotEqual では、第3引数に有効桁数を指定することができますので、浮動小数点型に対してこんな評価も可能です。

数値の範囲の評価

数値なら以下のメソッドで、指定の範囲内にあるか評価できます。

  • InRange<T>(T actual, T low, T high)
  • NotInRange<T>(T actual, T low, T high)

または、Assert.True 使ってこんな感じ: Assert.True( actual > lowValue && actual < highValue) でやると、より細かい評価も可能ですね。


#

bool の比較

このタイミングで書くのもなんですが、以下2つで評価ですね。引数にセットする値には、bool? 型も使えるとか、第2引数に userMessage つけれるとかありますが、これはもう他に書くこともないです。

  • Assert.True
  • Asset.False


object の評価

型の評価をする場合、以下を使えます。

  • Assert.IsType<T>(object actual)
  • Assert.IsNotType<T>(object actual)

個人的には、引数によって出力される型が異なる Factory メソッドとかで正しい型が出力されるかとかに使ったり。

また、親クラスのチェックには以下を使います(Generics じゃないメソッドもあるけど省略)。

  • Assert.IsAssignableFrom<T>(actual)


オブジェクトが同一インスタンスかどうかを評価するには、

  • Assert.Same(object expected, object actual)
  • Assert.NotSame(object expected, object actual)

があります。他にも、NotStrictEqual とかあるので、他に Object に対する評価をしたいときは、xUnit の実装やテストコードをみると、全部のメソッドが確認できます。

(飽きてだんだん雑になってきた...)

Collection の評価

コレクションの評価としては、まず、期待値(コレクションではない単体)がテスト対象のコレクションに含まれるかというチェックがあります。

  • Contains<T>(T expected, IEnumerable<T> collection)
  • DoesNotContain<T>(T expected, IEnumerable<T> collection)

Collection評価時の ContainsDoesNotContain には、引数に Predicate や IEqualityComparer を指定する方法もあります。

EqualNotEqual を使ってコレクション同士の比較をすることも可能です。また、LINQ にあるような SingleAll もあります。


Exception の評価

特定のメソッドとかで exception を発生させるなら以下で評価きます。

  • Assert.Throws(Action)

Exception 発生時の Parameter 名を指定して動かすこともテストもできます。

独自の Exception クラスを実装しているときは、2つの評価でテストするってパターンもありますね。

// 例えば "CustomException" クラスという独自の Exception クラスを用意して、例外発生後に特定のプロパティ
CustomException ex = Assert.Throws<CustomException>(Action)
Assert.Equal(expected, ex.SomeProperty)

その他

Event 関連の Assert も色々ありますが、私が Desktop アプリをあまり作らないので省略。

チートシート

他のテストライブラリーとの Assert や Attribute の比較は、以下になります。

Comparing xUnit.net to other frameworks

チートシートなだけで、Assert のメソッドが全部乗ってるわけでもないので、細かいこと確認したいときは、
xUnit の GitHub のテストメソッドとかを見て確認すると早いかなーと思っています。

github.com


次は、テストデータの作り方入門です。

beachside.hatenablog.com