10

単体テストを書く習慣を身に付けようとしています。以前にいくつか書いたことがありますが、通常は非常に基本的なものでした...品質を向上させたいので、TDD への移行を開始したいと思います。私のコード(設計と構造)の - カップリングを減らすと同時に、テスト可能なビルドにすり抜ける回帰の数を減らすことができれば幸いです。

私は最初に取り組んでいる比較的単純なプロジェクトを取りました。結果として得られるプログラムは、フォルダーを監視し、このフォルダー内のファイルに作用します。

プロジェクトから抽出されたコードの典型的な例を次に示します。

private string RestoreExtension(String file)
    {
        var unknownFile = Path.GetFileName(file);
        var ignoreDir = Path.GetDirectoryName(file) + "\\Unknown";
        string newFile;

        //We need this library for determining mime
        if (CheckLibrary("urlmon.dll"))
        {
            AddLogLine("Attempting to restore file extension");
            var mime = GetMimeType(BufferFile(file, 256));
            var extension = FileExtensions.FindExtension(mime);
            if (!String.IsNullOrEmpty(extension))
            {
                AddLogLine("Found extension: " + extension);
                newFile = file + "." + extension;
                File.Move(file, newFile);
                return newFile;
            }
        }
        else
        {
            AddLogLine("Unable to load urlmon.dll");
        }

        AddLogLine("Unable to restore file extension");

        if (!Directory.Exists(ignoreDir))
        {
            Directory.CreateDirectory(ignoreDir);
        }
        var time = DateTime.Now;
        const string format = "dd-MM-yyyy HH-mm-ss";

        newFile = ignoreDir + "\\" + unknownFile + "-" + time.ToString(format);
        File.Move(file, newFile);

        return String.Empty;
    }

質問:

IO を使用してメソッドをテストするにはどうすればよいですか? これは遅いので(そして統合テストのほうが多いのでしょうか)、実際のファイルを使用したくありませんが、別の方法が本当にわかりません。切り替え可能な IO 抽象化レイヤーを追加することもできますが、コードが不必要に複雑になる可能性があるように思えます...

このようなプロジェクトは単体テストの価値がありますか? というか、単純すぎるかな。.Net とサード パーティのライブラリ呼び出しを削除すると、ほとんど残っていません。テスト可能にするための作業量が、テストするのに適していないことを意味する場合はありますか?

このプロジェクトはたまたま Windows サービスであるため、このプロジェクトの多くのメソッドは非公開です。外部から見える (パブリックまたはインターフェイスを介して公開される) メソッドのみを実際にテストする必要があることを読みましたが、この場合、独自のメソッドを公開することはほとんどありません。このプロジェクトはテストする価値がありますか (id はおそらくメソッド アクセス修飾子を public に変更するか、いくつかの属性を追加して NUnit がそれらを認識できるようにする必要があるため)?

4

4 に答える 4

7

IO を使用してメソッドをテストするにはどうすればよいですか?

.NET の IO ライブラリに抽象化を導入し、アプリケーションで実際の実装 (BCL) を使用し、単体テストで偽の (モック) 実装を使用します。このような抽象化は自分で書くのはかなり簡単ですが、それらのプロジェクトは既に存在するため (例: System.IO.Abstraction )、特にそのような些細な問題では、車輪の再発明は無意味です。

これは遅いので、実際のファイルを使用したくありません

これは正しいです。テストでは、偽の(モック) オブジェクトを使用したいと考えています。

このようなプロジェクトは単体テストの価値がありますか?

すべてのプロジェクトはテストする価値があり、何らかの方法でテストします (最も極端な場合は、アプリケーションを手動で実行し、古き良きクリック アンド ウェイト テストを行うことです)。

ほとんどの場合、複雑なパーサー メソッドの 10 のエッジ ケースを手動でテストするには時間がかかりすぎることに注意してください。毎回大きなファイルを読み込んで結果を待つ必要があります。ここで、隔離された環境での自動テストが大いに役立ちます。コードでも同じです。ファイル システム、Web サービス、これらはすべて、実際のビジネス ロジックに到達する前に大きなオーバーヘッドをもたらします。隔離する必要があります。

このプロジェクトの多くのメソッドは非公開です (...) 外部から見えるメソッドのみを実際にテストする必要があることを読みました

繰り返しますが、パブリック コントラクトをテストする必要があります。ただし、プライベートなものがそれをテストするのに十分な大きさになった場合、ほとんどの場合、それは独自のクラスに入れるのに十分な大きさでもあることを示す良い指標です。単体テストの使用のためだけにメンバー アクセス修飾子を変更することは、最善の考えではないことに注意してください。ほとんどの場合、クラス/メソッドのリファクタリングを抽出する方が適切です。

于 2013-05-14T13:38:03.040 に答える
1

Microsoft Fakesを使用してそれを行うことができます。最初に System.dll またはその他のパッケージの偽のアセンブリを生成し、次のように予想される戻り値をモックします。

using Microsoft.QualityTools.Testing.Fakes;
...
using (ShimsContext.Create())
{
     System.IO.Fakes.ShimDirectory.ExistsString = (p) => true;
     System.IO.Fakes.ShimFile.MoveStringString = (p,n) => {};
     // .. and other methods you'd like to test

     var result = RestoreExtension("C:\myfile.ext");
     // then you can assert with this result 
}
于 2018-01-25T02:57:18.040 に答える
-1

私もTDDにはかなり慣れていませんが、あなたにいくつかの提案を得ることができると思います:

  1. IO テストについて。モック オブジェクトを使用できます。テストするメソッドのモックを作成し、実際に渡された値と比較します。Moq フレームワークでは、次のようになります。

    var mock = new Mock<IRepository<PersonalCabinetAccount>>();
    mock.Setup(m => m.RemoveByID(expectedID))
        .Callback((Int32 a) => Assert.AreEqual(expectedID, a));
    
    var account = new PersonalCabinetAccount {ID = myID};
    var repository = mock.Object;
    repository.RemoveByID(account.myId);
    
  2. はいぜったいに。習慣を身につけたいなら、すべてをテストする必要があると思います。そうすれば知識が得られます;)

  3. InternalsVisibleTo属性を使用して、可視性の問題を回避できます。

    外部から見えるテスト方法

これはエンタープライズプログラミングに関するものだと思います。独自の信頼できるコードを使用して時間を割くだけです。

私のポイントがあなたを助けることを願っています。

于 2013-05-14T12:19:25.610 に答える