Dinamik sayıda test ile JUnit testi


95

Projemizde , örneğin her dosyayı bir dizinden alıp üzerinde bir test çalıştıran birkaç JUnit testim var. Buna bir testEveryFileInDirectoryyöntem uygularsam TestCase, başarısız veya başarılı olabilecek tek bir test olarak görünür. Ancak her bir dosyadaki sonuçlarla ilgileniyorum. Her dosyanın ayrı bir test olarak görünmesi için nasıl bir TestCase/ TestSuiteböyle yazabilirim, örneğin Eclipse'in grafiksel TestRunner'ında? (Her dosya için açık bir test yöntemi kodlamak bir seçenek değildir.)

Ayrıca ParameterizedTest sorusunu Eclipse Testrunner'daki bir adla karşılaştırın .


Yanıtlar:


102

JUnit 4'teki Parametreli Testlere bir göz atın .

Aslında bunu birkaç gün önce yaptım. Açıklamaya çalışacağım ...

Öncelikle, yalnızca bir girdi dosyasıyla test ederken, test sınıfınızı normal şekilde oluşturun. Sınıfınızı şununla dekore edin:

@RunWith(Parameterized.class)

Her test çağrısında değişecek girdiyi alan bir kurucu oluşturun (bu durumda dosyanın kendisi olabilir)

Ardından, bir Collectiondizi döndürecek statik bir yöntem oluşturun . Koleksiyondaki her dizi, sınıf oluşturucunuz için, örneğin dosya için girdi bağımsız değişkenlerini içerecektir. Bu yöntemi şununla dekore edin:

@Parameters

İşte örnek bir sınıf.

@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;
    }
}

Ayrıca bu örneğe bakın


1
Teşekkürler! JUnit 4 Metodu, başka bir cevapta verilen JUnit 3 Metodu'ndan daha iyidir, çünkü JUnit 3, tutulma test koşucusunu karıştırır ve JUnit 4 Metodu ile testleri yeniden çalıştırabilirsiniz vs. testin adı - yalnızca [0], [1] gösterir vb.
Hans-Peter Störr

@hstoerr, Görünüşe göre bu JUnit'in bir sonraki sürümünde olacak :-) github.com/KentBeck/junit/commit/…
rescdsk

Her çalıştırmanın [farklı bir veri kombinasyonuyla] test çalıştırmasının adını değiştirmesini isteseydiniz, bunu nasıl dönüştürürdünüz? [Yani Path1 dosyası şu şekilde test edilecektir: 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 Parametreli Testler

JUnit 5 parametreli testleri, bir yöntemin veri kaynağı olarak kullanılmasına izin vererek bunu destekler :

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

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

JUnit 5 Dinamik Testleri

JUnit 5 , bunu , statik yöntemle a'da DynamicTestüretilecek olan a kavramı aracılığıyla da destekler .@TestFactorydynamicTest

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'nizde (IntelliJ burada) çalıştırılan testler şu şekilde görüntülenecektir:

IntelliJ'de çıktı


3

JUnit 3'te , dosyaları listelemek TestSuiteiçin tests()yöntemin miras alınması ve geçersiz kılınmasıyla mümkün olmalıdır ve her biri için bir alt sınıfın bir örneğini döndürerek TestCase, dosya adını yapıcı parametresi olarak alan ve yapıcıda verilen dosyayı test eden bir test yöntemine sahip olmalıdır.

JUnit 4'te daha da kolay olabilir.


2

JUnitParams kitaplığını kullanmayı düşünebilirsiniz , böylece birkaç (daha temiz) seçeneğiniz olur:

@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);
    }
}

Daha fazla kullanım örneğini burada görebilirsiniz .

JUnitParams hakkında ek olarak , parametreleştirilmiş testleri yazmanın neden daha kolay ve daha okunaklı olduğu :

JUnitParams projesi, JUnit'e yeni bir koşucu ekler ve JUnit> = 4.6 için çok daha kolay ve okunabilir parametreleştirilmiş testler sağlar.

Standart JUnit Parametrelendirilmiş koşucu ile ana farklar

  • daha açık - parametreler, sınıf alanları değil, test yöntemi parametrelerindedir
  • daha az kod - parametreleri ayarlamak için bir kurucuya ihtiyacınız yoktur
  • tek bir sınıfta parametreleştirilmiş ve parametreleştirilmemiş yöntemlerle karıştırabilirsiniz
  • parametreler bir CSV dizesi olarak veya bir parametre sağlayıcı sınıfından geçirilebilir
  • parametreler sağlayıcı sınıfı, istediğiniz kadar yöntem sağlayan parametrelere sahip olabilir, böylece farklı durumları gruplayabilirsiniz
  • parametreler sağlayan bir test yöntemine sahip olabilirsiniz (artık harici sınıflar veya statikler yok)
  • IDE'nizde gerçek parametre değerlerini görebilirsiniz (JUnit's Parametrised'de yalnızca ardışık sayıda parametre vardır)

1

TestNG bir seçenekse, DataProviders ile Parametreleri kullanabilirsiniz .

Her bir dosyanın testinin sonucu, metin tabanlı raporda veya Eclipse'in TestNG eklentisi kullanıcı arayüzünde gösterilecektir. Çalıştırılan toplam test sayısı, dosyalarınızın her birini ayrı ayrı sayacaktır.

Bu davranış , tüm sonuçların bir "teori" girişi altında toplandığı ve yalnızca 1 test olarak sayıldığı JUnit Teorilerinden farklıdır . JUnit'te ayrı sonuç raporlaması istiyorsanız, Parametreli Testleri deneyebilirsiniz .

Test ve girişler

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
    }
}

Örnek çıktı

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

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

Teorileri bilmiyorum, ancak JUnit'teki parametreli testler tutulmada ayrı ayrı gösteriliyor, bir araya toplanmıyor.
Hans-Peter Störr

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.