NUnitのテキストファイルを比較するための単体テスト
-
02-07-2019 - |
質問
2つのxmlファイルを処理してテキストファイルを生成するクラスがあります。
次のことを行うこのクラスに対して個別に合格または不合格になることができるユニット/統合テストの束を書きたいと思います:
- 入力AおよびBの場合、出力を生成します。
- 生成されたファイルの内容を、期待される内容と比較する
- 実際のコンテンツが予想されたコンテンツと異なる場合、失敗し、その違いに関するいくつかの有用な情報を表示します。
以下は、クラスのプロトタイプであり、ユニットテストでの最初のスタブです。
この種のテストに使用すべきパターンはありますか、それとも人々は無数のTestX()関数を書く傾向がありますか?
テキストファイルの違いをNUnitと同軸にするより良い方法はありますか?テキストファイルの差分アルゴリズムを埋め込む必要がありますか?
class ReportGenerator
{
string Generate(string inputPathA, string inputPathB)
{
//do stuff
}
}
[TextFixture]
public class ReportGeneratorTests
{
static Diff(string pathToExpectedResult, string pathToActualResult)
{
using (StreamReader rs1 = File.OpenText(pathToExpectedResult))
{
using (StreamReader rs2 = File.OpenText(pathToActualResult))
{
string actualContents = rs2.ReadToEnd();
string expectedContents = rs1.ReadToEnd();
//this works, but the output could be a LOT more useful.
Assert.AreEqual(expectedContents, actualContents);
}
}
}
static TestGenerate(string pathToInputA, string pathToInputB, string pathToExpectedResult)
{
ReportGenerator obj = new ReportGenerator();
string pathToResult = obj.Generate(pathToInputA, pathToInputB);
Diff(pathToExpectedResult, pathToResult);
}
[Test]
public void TestX()
{
TestGenerate("x1.xml", "x2.xml", "x-expected.txt");
}
[Test]
public void TestY()
{
TestGenerate("y1.xml", "y2.xml", "y-expected.txt");
}
//etc...
}
更新
diff機能のテストには興味がありません。より読みやすいエラーを生成するために使用したいだけです。
解決
異なるデータを使用する複数のテストについては、NUnit RowTest拡張機能を使用します。
using NUnit.Framework.Extensions;
[RowTest]
[Row("x1.xml", "x2.xml", "x-expected.xml")]
[Row("y1.xml", "y2.xml", "y-expected.xml")]
public void TestGenerate(string pathToInputA, string pathToInputB, string pathToExpectedResult)
{
ReportGenerator obj = new ReportGenerator();
string pathToResult = obj.Generate(pathToInputA, pathToInputB);
Diff(pathToExpectedResult, pathToResult);
}
他のヒント
おそらく、「ゴールド」に対するテストを求めているでしょう。データ。世界中で受け入れられているこの種のテストに特定の用語があるかどうかはわかりませんが、これが私たちのやり方です。
ベースフィクスチャクラスを作成します。基本的に" void DoTest(string fileName)"があり、特定のファイルをメモリに読み込み、抽象変換メソッド" string Transform(string text)"を実行し、同じ場所からfileName.goldを読み取り、変換されたテキストを比較します期待されたもので。コンテンツが異なる場合、例外がスローされます。スローされる例外には、最初の違いの行番号と、予想される行と実際の行のテキストが含まれます。テキストは安定しているため、通常、これは問題をすぐに見つけるのに十分な情報です。必ず" Expected:"で行をマークしてください。および「Actual:"」、またはテスト結果を見るときにどちらが永遠に推測されるのでしょうか。
次に、特定のテストフィクスチャがあり、適切なジョブを実行するTransformメソッドを実装し、次のようなテストを実行します。
[Test] public void TestX() { DoTest("X"); }
[Test] public void TestY() { DoTest("Y"); }
失敗したテストの名前により、何が壊れているかがすぐにわかります。もちろん、行テストを使用して同様のテストをグループ化できます。テストを個別に持つことは、テストを無視したり、同僚にテストを伝えたりするなど、多くの状況でも役立ちます。すぐにテストを作成するスニペットを作成することは大したことではありません。データの準備により多くの時間を費やすことになります。
次に、いくつかのテストデータと、ベースフィクスチャがそれを見つける方法も必要になります。プロジェクトのルールを必ず設定してください。テストが失敗した場合、実際の出力をゴールドの近くのファイルにダンプし、テストに合格した場合は消去します。このようにして、必要なときにdiffツールを使用できます。ゴールドデータが見つからない場合、テストは適切なメッセージで失敗しますが、実際の出力はとにかく書き込まれるため、それが正しいことを確認し、コピーして「ゴールド」になることができます。
おそらく、ループを含む単一の単体テストを作成します。ループ内で、2つのxmlファイルとdiffファイルを読み取り、xmlファイルを(ディスクに書き込まずに)diffし、ディスクから読み取ったdiffファイルと比較します。ファイルには番号が付けられます。 a1.xml、b1.xml、diff1.txt; a2.xml、b2.xml、diff2.txt; a3.xml、b3.xml、diff3.txtなど。次の番号が見つからない場合、ループは停止します。
その後、新しいテキストファイルを追加するだけで新しいテストを作成できます。
.AreEqualを呼び出す代わりに、2つの入力ストリームを自分で解析し、行と列のカウントを保持して、内容を比較できます。違いを見つけたらすぐに、次のようなメッセージを生成できます...
行32列12-「y」が予期されていたときに「x」が見つかりました
必要に応じて、複数行の出力を表示して機能を強化できます
32行目、12列目の違い、最初の違いを表示
です
A =これはt x st
です B =これはt e sts
原則として、私は通常、自分のコードから、あなたが持っている2つのストリームのうちの1つだけを生成します。もう1つは、目または他の方法で、含まれているデータが正しいことを確認したテスト/テキストファイルから取得します!
おそらくXmlReaderを使用してファイルを反復処理し、それらを比較します。違いが見つかったら、ファイルが異なる場所へのXPathを表示します。
PS:しかし、実際には、ファイル全体を文字列に単純に読み取り、2つの文字列を比較するだけで十分でした。レポートについては、テストが失敗したことを確認するだけで十分です。その後、デバッグを行うとき、通常、 Araxis Merge を使用してファイルを比較し、正確にどこを確認します問題があります。