web-dev-qa-db-ja.com

ファイル形式変換ユーティリティの単体テストケースを作成するにはどうすればよいですか?

1つのファイル形式を別のファイル形式に変換する1つのユーティリティモジュールを作成しました。ファイルi.e。test.abci.e。test.pqrに変換され、ファイルの内部形式は完全に異なります。このモジュールには、ほぼ5つの異なるファイル形式が含まれます。

内部、1つのネイティブツールを使用しており、私はそれを制御できません。それはファイルを変換し、私のユーティリティクラスはこのツールにコマンドを送信し、ファイルを操作します。

public class Utility {

     public File convertIt(File file, Format to) {
        // Check extension
        // Execute command of native tool accordingly
        // Return resulting file
     }
}

このユーティリティの単体テストケースをどのように記述すればよいか判断できません。各フォーマットは異なるため、制作時にはすべてのファイルがユーザーによって挿入されます。さらに、いくつかの属性は必須であり、一部はオプションです。また、1つのファイル形式で使用する場合と使用しない場合があります。

現在私が考えているのは、テストケースのリソースで、すでに持っているすべての入力ファイルと結果ファイルを提供できることです。次に、各呼び出しの出力を既存の出力ファイルと比較します。ただし、これですべてのシナリオがカバーされるわけではなく、テスト用にさらにファイルが必要になる場合があります。

- resources
       |- input
            |- input1.abc
            |- input2.pqr
            |- input3.xyz
       |- output
            |- output1.xyz
            |- output2.abc
            |- output3.pqr

私の質問、

  • このアプローチは正しいですか?
  • 他にbetterアプローチはありますか?
  • ファイルを操作するそのようなメソッドをテストするためのベストプラクティスは何ですか?
4
CoderCroc

基本的にネイティブツールのラッパーであるコードをテストします。

完璧です。ネイティブツールをテストする場合は、コードを使用してテストすることはありません。したがって、入力ファイルや出力ファイルを作成する必要はありません。ネイティブツールが正しい引数で呼び出されるようにするだけです。

1つの方法は、コマンドを実行できるExecutorクラスを作成し、それをコンバーターに渡すことです。

class Converter {
    private Executor executor;

    public Converter(Executor executor) {
        this.executor = executor;
    }

    convertIt() {
        command = ...
        executor.execute(command);
    }
}

}

次に、 Mockito を使用して、テスト用の模擬エグゼキューターを作成します。 junit を使用すると、テストメソッドの作成と実行が簡単になります。

import org.junit.Test;
import static org.mockito.Mockito.*;

class ConverterTest {
    private Executor executor;

    @Before
    public void setup() {
         executor = mock(Executor.class);
    }

    @Test
    public void TestAtoB() {
        String expectedCommand = ...;
        Converter converter = new Converter(executor);
        converter.convert(...);
        verify(executor).execute(expectedCommand);
    }
}
3
kevin cline

まず第一に、知識のポイント。これらのテストはファイルを読み書きする外部ユーティリティを呼び出しているため、これらのテストは実際には統合テストです。単体テストではありません。

そのサウンドによって、特定の入力ファイルタイプと選択された出力タイプに対して、ユーティリティのセットを提供し、それらのパラメータは各入力/出力の組み合わせごとに変化します。これが正しいと仮定して、メソッドを適切にテストするためのアプローチは(現時点では)良いものです。それぞれの組み合わせに対して適切な出力ファイルを作成する必要があります。これにより、メソッド(および結果のユーティリティ呼び出し)を通るすべてのパスをテストできます。

それが理想的とは言えないアプローチは、ユーティリティが将来変更される可能性に関してです。ツールの新しいバージョンで出力ファイルが変更された場合、ツールが変更されただけでテストは失敗します。コードに欠陥があるからではありません。したがって、あなたはもろいテストをしています。また、新しいバージョンでは、顧客のためにファイルをより適切に変換するためのより多くの属性を提供する必要がありますが、テストはこれらの新機能を必ずしもピックアップするわけではありません。

したがって、テストを疑わしいものとして扱い、出力ファイルを再生成し、ユーティリティの新しいバージョンがリリースされるたびに属性の変更を確認するワークフローが必要になる可能性があります。これを適切に配置すれば、このテストアプローチは適切です。

2
David Arno

彼自身のコメントにも関わらず、私はOP doesは潜在的なコンバーターを暗黙的にテストしたいと考えています。

どうして?ラッパーの単体テストはほとんど役に立ちません(ただし、非常に複雑ですが、より小さく複雑でない部分に分割する必要があります)。基礎となるlibの呼び出しを正しく行い、引数が正しく渡される場合にのみテストできます。しかし、最初の数回の手動テストでそれがわかるでしょう。

特に興味深いのは、特にコーナーケースでlibが期待どおりに動作するかどうかです(たとえば、.abcは.xyzに必須のパラメーターを定義していません)。さらに、新しいバージョンにアップグレードするときに、libが同じ動作をする場合。

最後に、あなたのアプローチは良いです、ちょうど2つのメモ:

  • 少数の標準的なケース(煙のテスト)だけをテストしてみてください。
  • リソースファイルには別の構造を使用します(もっと便利だと思いますが、好みの問題です):resources/abc to xyz/missing params/input.abc、expected.xyz
1
Andy