使用动态测试次数进行JUnit测试

时间:2008-12-11 09:39:45

标签: java unit-testing junit parameterized-unit-test

在我们的项目中,我有几个JUnit测试,例如从目录中获取每个文件并对其运行测试。如果我在testEveryFileInDirectory中实现TestCase方法,则只显示一个可能失败或成功的测试。但我对每个文件的结果感兴趣。如何撰写TestCase / TestSuite,以便每个文件都显示为单独的测试,例如在Eclipse的图形化TestRunner中? (为每个文件编写显式测试方法不是一种选择。)

还要比较问题ParameterizedTest with a name in Eclipse Testrunner

7 个答案:

答案 0 :(得分:98)

在JUnit 4中查看参数化测试

其实我几天前这样做过。我会试着解释一下......

首先正常构建您的测试类,就像您只使用一个输入文件进行测试一样。 用:

装饰你的班级
@RunWith(Parameterized.class)

构建一个构造函数,该构造函数接受将在每次测试调用中更改的输入(在这种情况下,它可能是文件本身)

然后,构建一个返回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;
    }
}

同时检查此example

答案 1 :(得分: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());
    }

}

答案 2 :(得分:8)

Junit 5参数化测试

JUnit 5参数化测试通过允许使用method as data source

来支持此功能
@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通过静态方法dynamicTestimport 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 */ })); } 中生成。

      <Package
      ...
      xmlns:uap2="http://schemas.microsoft.com/appx/manifest/uap/windows10/2"
      xmlns:uap3="http://schemas.microsoft.com/appx/manifest/uap/windows10/3"
      xmlns:desktop="http://schemas.microsoft.com/appx/manifest/desktop/windows10"
      ...
      IgnorableNamespaces="uap uap2 uap3 mp rescap desktop">

在IDE中运行的测试(此处为IntelliJ)将显示如下:

Output in IntelliJ

答案 3 :(得分:3)

应该可以在JUnit 3中继承TestSuite并重写tests()方法列出文件,并且每次返回TestCase子类的实例,该文件的文件名为构造函数参数,并有一个测试方法,用于测试构造函数中给出的文件。

在JUnit 4中,它可能更容易。

答案 4 :(得分:2)

你可以考虑使用JUnitParams library,这样你就可以有更多(更干净)的选择:

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

您可以看到更多samples of usage here

另外about JUnitParams, why writting parameterized tests with it is easier and more readable

  

JUnitParams项目为JUnit添加了一个新的运行器并提供了很多   JUnit&gt; = 4.6的简单易读的参数化测试。

     

与标准JUnit Parametrised跑步者的主要区别:

     
      
  • 更明确 - params在测试方法参数中,而不是类字段
  •   
  • 更少的代码 - 您不需要构造函数来设置参数
  •   
  • 您可以将参数化与非参数化方法混合在一个类
  • 中   
  • params可以作为CSV字符串或参数提供程序类
  • 传递   
  • 参数提供程序类可以根据需要提供尽可能多的参数,以便您可以对不同的情况进行分组
  •   
  • 您可以拥有一个提供参数的测试方法(不再需要外部类或静态)
  •   
  • 您可以在IDE中看到实际的参数值(在JUnit的Parametrised中它只是连续的参数数量)
  •   

答案 5 :(得分:1)

如果选择TestNG,您可以使用Parameters with DataProviders

每个单独文件的测试都会在基于文本的报告或Eclipse的TestNG插件UI中显示其结果。运行的总测试次数将分别计算每个文件。

此行为与JUnit Theories不同,其中所有结果都集中在一个“理论”条目下,并且仅计为1个测试。如果您想在JUnit中单独进行结果报告,可以尝试Parameterized Tests

测试和输入

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

答案 6 :(得分:0)

我遇到了类似的问题,最后编写了一个简单的JUnit 4运行程序,允许med动态生成测试。

https://github.com/kimble/junit-test-factory