動的な数のテストを伴うJUnitテスト


95

私たちのプロジェクトでは、たとえば、ディレクトリからすべてのファイルを取得し、その上でテストを実行する、いくつかのJUnitテストがあります。私がtestEveryFileInDirectoryメソッドを実装した場合、TestCaseこれは失敗または成功する可能性のある1つのテストのみとして表示されます。しかし、私は個々のファイルの結果に興味があります。たとえば、EclipseのグラフィカルなTestRunnerで、各ファイルが個別のテストとして表示されるようにTestCase/ を書くにはどうすればよいTestSuiteですか?(各ファイルの明示的なテスト方法をコーディングすることはオプションではありません。)

質問ParameterizedTestとEclipse Testrunnerの名前も比較してください。


回答:


102

JUnit 4のパラメーター化されたテストを見てください。

実際、私は数日前にこれを行いました。説明しようと思います...

まず、1つの入力ファイルでテストするのと同じように、通常どおりテストクラスをビルドします。クラスを次のように装飾します。

@RunWith(Parameterized.class)

すべてのテスト呼び出しで変更される入力を受け取る1つのコンストラクターを作成します(この場合はファイル自体の可能性があります)。

次に、Collection配列のを返す静的メソッドを作成します。コレクションの各配列には、ファイルなどのクラスコンストラクターの入力引数が含まれます。このメソッドを次のように装飾します。

@Parameters

ここにサンプルクラスがあります。

@RunWith(Parameterized.class)
public class ParameterizedTest {

    private File file;

    public ParameterizedTest(File file) {
        this.file = file;
    }

    @Test
    public void test1() throws Exception {  }

    @Test
    public void test2() throws Exception {  }

    @Parameters
    public static Collection<Object[]> data() {
        // load the files as you want
        Object[] fileArg1 = new Object[] { new File("path1") };
        Object[] fileArg2 = new Object[] { new File("path2") };

        Collection<Object[]> data = new ArrayList<Object[]>();
        data.add(fileArg1);
        data.add(fileArg2);
        return data;
    }
}

このも確認してください


1
ありがとう!JUnit 4メソッドは別の回答で示されているJUnit 3メソッドよりも優れています。JUnit3はEclipseテストランナーを混同するため、JUnit 4メソッドを使用するとテストを再実行できるなどです。テストの名前-[0]、[1]などのみを表示します
Hans-PeterStörr

@hstoerr、このように見えますがJUnitの:-)の次のリリースになりますgithub.com/KentBeck/junit/commit/...
rescdsk

各実行[異なるデータの組み合わせ]でテスト実行の名前を変更したい場合、これをどのように変換しますか?[Path1ファイルは次のようにテストされます:test1Path1、test2Path?
monksy


27

JUnit 3

public class XTest extends TestCase {

    public File file;

    public XTest(File file) {
        super(file.toString());
        this.file = file;
    }

    public void testX() {
        fail("Failed: " + file);
    }

}

public class XTestSuite extends TestSuite {

    public static Test suite() {
        TestSuite suite = new TestSuite("XTestSuite");
        File[] files = new File(".").listFiles();
        for (File file : files) {
            suite.addTest(new XTest(file));
        }
        return suite;
    }

}

JUnit 4

import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import org.junit.runners.Parameterized.Parameters;

@RunWith(Parameterized.class)
public class TestY {

    @Parameters
    public static Collection<Object[]> getFiles() {
        Collection<Object[]> params = new ArrayList<Object[]>();
        for (File f : new File(".").listFiles()) {
            Object[] arr = new Object[] { f };
            params.add(arr);
        }
        return params;
    }

    private File file;

    public TestY(File file) {
        this.file = file;
    }

    @Test
    public void testY() {
        fail(file.toString());
    }

}

11

JUnit 5パラメータ化テスト

JUnit 5のパラメーター化されたテストは、データソースとしてメソッドを使用できるようにすることでこれをサポートします

@ParameterizedTest
@MethodSource("fileProvider")
void testFile(File f) {
    // Your test comes here
}

static Stream<File> fileProvider() {
    return Arrays.asList(new File(".").list()).stream();
}

JUnit 5 DynamicTests

JUnit 5は、静的メソッドをDynamicTest使用して@TestFactoryで生成されるの概念を通じてこれもサポートしますdynamicTest

import org.junit.jupiter.api.DynamicTest;
import org.junit.jupiter.api.TestFactory;
import static org.junit.jupiter.api.DynamicTest.dynamicTest;

import java.util.stream.Stream;

@TestFactory
public Stream<DynamicTest> testFiles() {
    return Arrays.asList(new File(".").list())
            .stream()
            .map((file) -> dynamicTest(
                    "Test for file: " + file,
                    () -> { /* Your test comes here */ }));
}

IDE(ここではIntelliJ)で実行されたテストは、次のように表示されます。

IntelliJでの出力


3

JUnit 3 TestSuiteでは、tests()メソッドを継承およびオーバーライドしてファイルをリストし、それぞれについてサブクラスのインスタンスを返すことで、JUnit 3で可能になるはずです。TestCase、ファイル名をコンストラクターパラメーターとして受け取り、コンストラクターで指定されたファイルをテストするテストメソッドを持つです。

JUnit 4ではさらに簡単になる可能性があります。


2

JUnitParamsライブラリの使用を検討して、さらにいくつかの(よりクリーンな)オプションを使用できます。

@org.junit.runner.RunWith(junitparams.JUnitParamsRunner.class)
public class ParameterizedTest {

    @org.junit.Test
    @junitparams.Parameters(method = "data")
    public void test1(File file) throws Exception {  }

    @org.junit.Test
    @junitparams.Parameters(method = "data")
    public void test2(File file) throws Exception {  }

    public static File[] data() {
        return new File[] { new File("path1"), new File("path2") };
    }
}

@org.junit.runner.RunWith(junitparams.JUnitParamsRunner.class)
public class ParameterizedTest {

    @org.junit.Test
    @junitparams.Parameters(value = { "path1", "path2" })
    public void test1(String path) throws Exception {
        File file = new File(path);
    }

    @org.junit.Test
    @junitparams.Parameters(value = { "path1", "path2" })
    public void test2(String path) throws Exception {
        File file = new File(path);
    }
}

あなたはここで使用のより多くのサンプルを見ることができます

さらに、JUnitParamsについて、パラメーター化されたテストの記述が簡単で読みやすい理由

JUnitParamsプロジェクトは、JUnitに新しいランナーを追加し、JUnit> = 4.6のはるかに簡単で読みやすいパラメーター化されたテストを提供します。

標準のJUnit Parametrisedランナーとの主な違い:

  • より明示的-パラメータは、クラスフィールドではなく、テストメソッドのパラメータにあります
  • 少ないコード-パラメータを設定するためにコンストラクタは必要ありません
  • パラメータ化されたメソッドとパラメータ化されていないメソッドを1つのクラスで混在させることができます
  • パラメータは、CSV文字列として、またはパラメータプロバイダクラスから渡すことができます。
  • パラメータープロバイダークラスには、メソッドを提供するパラメーターを必要な数だけ含めることができるため、さまざまなケースをグループ化できます。
  • パラメータを提供するテストメソッドを持つことができます(外部クラスや静的クラスはもうありません)
  • IDEで実際のパラメーター値を確認できます(JUnitのParametrisedでは、パラメーターの連続した数のみです)

1

TestNGがオプションの場合は、DataProvidersでパラメーターを使用できます。

個々のファイルのテストごとに、テキストベースのレポートまたはEclipseのTestNGプラグインUIに結果が表示されます。実行されるテストの総数は、ファイルごとに個別にカウントされます。

この動作はJUnit 理論とは異なります。JUnit 理論では、すべての結果が1つの「理論」エントリにまとめられ、1つのテストとしてのみカウントされます。JUnitで個別の結果レポートが必要な場合は、パラメーター化されたテストを試すことができます

テストと入力

public class FileTest {

    @DataProvider(name="files")
    public File[][] getFiles(){
        return new File[][] {
            { new File("file1") },
            { new File("file2") }
        };
        // or scan a directory
    }

    @Test(dataProvider="files")
    public void testFile(File file){
        //run tests on file
    }
}

出力例

PASSED: testFile(file1)
PASSED: testFile(file2)

===============================================
    Default test
    Tests run: 2, Failures: 0, Skips: 0
===============================================

理論については知りませんが、JUnitのパラメーター化されたテストは、まとめてではなく、Eclipseで個別に表示されます。
Hans-PeterStörr2014

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