1

想像してみてください: 新しい機能を作成したいと考えています: ファイルのウイルスをスキャンします。

TDDを使用して、次のテストを行いたい:

  • ScanningAnInfectedFileReturnsFalse

  • ScanningACleanFileReturnsTrue

コードでは、この関数を作成したい:

/// <summary>
    /// 
    /// </summary>
    /// <param name="fullFileName">The File To Scan</param>
    /// <returns>True: File is clean, False: File contains virus</returns>
    public static bool ScanFile(string fullFileName)
    {
        //TODO: Scan the given FullFileName
        throw new NotImplementedException();
    }

私の質問: 指定された関数を使用して 2 つのテストを実装するにはどうすればよいですか? 関数をテスト可能にするためにリファクタリングする必要があると思いますか?

4

1 に答える 1

3

あなたが持っている問題は、ファイルへのパスを取ることによるこの方法はScanFile、テストするのを難しくするあまりにも多くの責任を持っているということです。

  • ファイルを開きます(そしてエラーに対処します)
  • ファイルの内容を読む
  • 内容に問題がないか判断してください*
  • ファイルを閉じる

注釈*が付けられた項目は、このメソッドが実行する必要があるすべてです。このようにして、メソッドははるかにテスト可能になります。

この変更を実装するための1つの可能な方法は、メソッドにインターフェースをとらせることです。

public bool ScanFile(IScannable file)
{

}

次に、スキャンメソッドが特定のバイトシーケンスを検索しているとすると、インターフェイスは次のように単純になります。

public interface IScannable
{
    byte[] GetContent();
}

次に、テストで2つのテストのこのインターフェイス(Rhino、NMockなどを参照)をモックするだけで、1つは不良なバイトシーケンスを返し、もう1つは良好なバイトシーケンスを返します。実際の実装は、具体的なクラスを持つのと同じくらい簡単です。

public class ScannableFile : IScannable
{
    private string fullFilename;
    public ScannableFile(string fullFilename)
    {
        this.fullFileName = fullFilename;
    }

    public byte[] GetContent()
    {
        return File.ReadAllBytes(this.fullFilename);
    }
}
于 2012-10-03T12:49:39.960 に答える