テスト駆動開発:ファイルシステム操作をテストするための良い/受け入れられた方法ですか?


14

私は現在、ファイルシステムの内容に基づいて(特に)テーブルを生成し、見つかったものに対してメタデータの変更を行うプロジェクトに取り組んでいます。問題は、これをどのようにテストするのか、セットアップするのかです。これを簡単にモックする方法はありますか?または、「サンドボックス」を設定する必要がありますか?

回答:


13

外部リソースを使用してTDDで常に行うように、ファイルシステム操作への1つ以上のインターフェイスを作成し、「モックアウト」します。ファイルシステム操作自体ではなく、「テーブルジェネレータ」とメタデータ変更コードをテストする必要があります(ほとんどの場合、ファイルシステムへのアクセスに既製のライブラリ実装を使用しています)。


TDDは、テスト対象のユニットの実装をモックすることを推奨していません。(E、G)を参照してくださいsolnic.eu/2014/05/22/mocking-and-ruby.html
soru

1
@soru:それはこの答えが推奨するものではありません。最初にインターフェイスを作成し、次にインターフェイスをモックすることをお勧めします。そのため、ビジネスロジックはテストしますが、ファイルシステムインターフェイスはテストしません。
sleske

5
しかし、ビジネスロジックはファイルとディレクトリの観点から定義されているようです。そのため、ファイルシステムAPIを呼び出すもの、テストが必要なものです。関連するファイル以外のビジネスロジックのテストには、モックは必要ありません。ただテストしてください。
-soru

@soru right、したがって、すべてのドメイン固有の操作がクライアント側で実行されるように定義されたインターフェイスでファイルとフォルダーの周りに薄いレイヤーを作成し、実装側はユニットテストなしで動作することを確信するのに十分簡単です(統合テストはまだ必要です)。uiコードでのHumble Dialogのアイデア、または永続オブジェクトで動作するコードでのモックリポジトリの使用に似ています。
ジュール

2
そのため、ファイルシステム、データベースなどとやり取りする実際のクラスのテストから効果的に辞任します...代わりに、モック/スタブと同じインターフェイスで別の実装を作成しますが、実際のクラスは単体テストなしで残します。単体テストはできないと考えているため、代わりに統合テストを実行してテストする必要があります。これは正しいです?
アンドリューサビニク

11

「テスト」ファイルシステムの問題は何ですか?

操作をテストするのに十分なコンテンツを含むテンプレートフォルダー/ディレクトリ構造を作成します。

ユニットテストのセットアップ中に、この初期構造をコピーします(テンプレートを圧縮してテスト領域に解凍することをお勧めします)。テストを実行します。分解中にすべてを削除します。

モックの問題は、最初にファイルシステム、プロジェクトに属するOSおよびデータベースが外部リソースとして実際に適格ではないこと、および2番目に低レベルのシステムコールをモックすると時間がかかり、エラーが発生しやすいことです。


5
ファイルシステムの操作をモックアウトすると、実際のファイルシステムを使用するよりもはるかに高速なテストが実行されます。これが「エラーを起こしやすい」かどうかは議論の余地がありますが、実装によって異なります。それにもかかわらず、自動化れた統合テストを作成するための提案はうまくいくと思います(通常、TDDを実行しないときに最初に行います)。しかし、OPは特別にTDDを要求し、TDDユニットテストは高速でなければなりません。
ドックブラウン

1
ファイルシステムでモックを作成する場合、理想的には、あるグループがAPI全体を作成および保守する必要があります。
フランクヒルマン

2
@Doc Brown-dir、delete、renameの各タイプの操作を行いたいと思っているようです。すべての操作には、モックに苦労するようなエッジケースがあります。また、最新のハードウェアでは、いくつかの小さなファイルをディレクトリに解凍するのは、Javaクラスをロードするよりも少し遅いだけです。
ジェームスアンダーソン

テストファイルシステムについて考えるほど、それが好きになります。
フランクヒルマン

3

これは、実際のファイルシステムにはあらゆる種類の奇妙な動作があるため、統合テストに必ず必要なものです(削除者を含むプロセスが開いている場合、Windowsがファイルの削除を許可しない方法など)。

そのため、TDDのアプローチでは、最初に統合テスト作成ます(厳密には、TDDには「単体テスト」と「統合テスト」という概念はありません。これらは単なるテストです)。それで十分でしょう。そのジョブは、ストップを行って、家に行きます

そうでない場合、ファイルを配置することで適切にテストするのは容易ではない内部の複雑さがあります。その場合、単純にその複雑さを取り除き、クラスに入れ、そのクラスの単体テストを作成します。その共通クラスは、データベース、xmlファイルなどのケースでも使用できることがわかるでしょう。

どのような場合でも、テスト対象のユニットが間違っているかどうかに合格するテストを作成するために、作成中のコードの基本的なコアを取り出して「モック」を作成することはありません。


この答えは私にとって本当に視点に入れています- 'unit test' and 'integration test'; they are just tests.現実的には、これは私のケースにとって最良のソリューションになると思います- エッジケースに使用しているファイルシステムライブラリとアプリケーションの応答方法をテストする必要がありますそれら。別のファイルシステムライブラリに切り替えた場合、新しいライブラリを使用するために多数のモック/テストコードを書き直す必要はありませんが、テストフォルダー構造と統合テストがあれば、より簡単になります。
tehDorf

2

私はあなたの質問を「ファイルシステムの操作に依存するクラスをテストする良い/受け入れられた方法」として理解しています。OSのファイルシステムをテストしたいとは思いません。

@Doc Brownの回答が可能な限り小さいと示唆したように、「ファイルシステム操作へのインターフェースと「モックアウト」」の努力を続けるために、Java バイナリストリームまたはテキストリーダー(またはc#で同等のもの)を使用することをお勧めします使用しているプログラミング言語)ファイルをファイル名で直接使用する代わりに、 tdd開発クラスで直接使用します

例:

Javaを使用して、クラスCsvReaderを実装しました

public class CsvReader {
    private Reader reader;

    public CsvReader(Reader reader) {
        this.reader = reader;
    }
}

テストのために、私はこのようなメモリデータを使用しました

String contentOfCsv = "TestColumn1;TestColumn2\n"+
    "value1;value2\n";

CsvReader sut = new CsvReader(java.io.StringReader(contentOfCsv));

またはリソースにテストデータを埋め込む

CsvReader sut = new CsvReader(getClass().getResourceAsStream("/data.csv"));

本番では、ファイルシステムを使用します

CsvReader sut = new CsvReader(new BufferedReader( new FileReader( "/import/Prices.csv" ) ));

このように、私のCsvReaderはファイルシステムに依存せず、ファイルシステムの実装がある抽象化「リーダー」に依存します。


2
ここでの唯一の問題は、OPは、ファイル操作を話していなかったということですが、ファイルシステムの操作とメタデータ操作は-私は彼がなどすべての画像ファイルの一部のEXIF情報を更新し、ディレクトリ内のすべてのファイルをリストのようなものを意味推測する
ドク・ブラウン

正解です。
-Kirbinator

1
メソッドString [] List(String directory)を持つIDirectoryListerを作成できます。FakeDirectoryListerは、新しいString [] {"。"、 ".."、 "foo.bat"、 "bar.exe"}を返すだけで、このメソッドを実装できます。
アンデルスリンデン

0

ファイルシステム操作のラッパーを作成します。テストでは、ラッパーと同じインターフェースを実装するモックを渡します。本番環境では、ラッパーを渡します。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.