How to attach a DataPoint with a Theory?

心已入冬 提交于 2019-12-04 00:17:18

DataPoints apply to the class. If you have a @Theory method which takes an int, and you have a DataPoint which is an array of ints, then it will be called with the int.

@RunWith(Theories.class)
public class TheoryTest {
    @DataPoint public static int input1 = 45;
    @DataPoint public static int input2 = 46;
    @DataPoints public static String[] inputs = new String[] { "foobar", "barbar" };

    @Theory public void testString1(String input) {
        System.out.println("testString1 input=" + input);
    }

    @Theory public void testString2(String input) {
        System.out.println("testString2 input=" + input);
    }

    @Theory public void test1(int input) {
        System.out.println("test1 input=" + input);
    }

    @Theory public void test2(int input) {
        System.out.println("test2 input=" + input);
    }
}

This calls test1 with 45 & 46, and test2 with 45 & 46. It calls testString1 with "foobar" and "barbar" and testString2 with "foobar" and "barbar".

If you really want to use different data sets for different theories, you can wrap the data in a private class:

@RunWith(Theories.class)
public class TheoryTest {
    public static class I1 { int i; public I1(int i) { this.i = i;} }
    public static class I2 { int i; public I2(int i) { this.i = i;} }

    @DataPoint public static I1 input1 = new I1(45);
    @DataPoint public static I2 input2 = new I2(46);

    @Theory
    public void test1(I1 input) {
        System.out.println("test1 input=" + input.i);
    }

    @Theory
    public void test2(I2 input) {
        System.out.println("test2 input=" + input.i);
    }
}

This calls test1 with 45 and test2 with 46. This works, but in my opinion, it obscures the code, and it may be a better solution to just split the Test class into two classes.

Gábor Lipták

With JUnit 4.12 (not sure when it was introduced) it is possible to name the DataPoints and assign them to parameters (i learned it from http://farenda.com/junit/junit-theories-with-datapoints/):

    @RunWith(Theories.class)
    public class TheoriesAndDataPointsTest {
        @DataPoints("a values")
        public static int[] aValues() {
            return new int[]{1, 2};
        }

        @DataPoints("b values")
        public static int[] bValues() {
            return new int[]{3, 4};
        }

        @Theory
        public void theoryForA(@FromDataPoints("a values") int a) {
            System.out.printf("TheoryForA called with a = %d\n", a);
        }

        @Theory
        public void theoryForB(@FromDataPoints("b values") int a) {
            System.out.printf("TheoryForB called with b = %d\n", a);
        }
    }

Output:

TheoryForA called with a = 1
TheoryForA called with a = 2
TheoryForB called with b = 3
TheoryForB called with b = 4

In reference to Gábor Lipták's answer, named datapoints can be defined as a static fields (reference) which give us more concise code:

    @RunWith(Theories.class)
    public class TheoriesAndDataPointsTest {
        @DataPoints("a values")
        public static int[] aValues = {1, 2};

        @DataPoints("b values")
        public static int[] bValues = {3, 4};

        @Theory
        public void theoryForA(@FromDataPoints("a values") int a) {
            System.out.printf("TheoryForA called with a = %d\n", a);
        }

        @Theory
        public void theoryForB(@FromDataPoints("b values") int a) {
            System.out.printf("TheoryForB called with b = %d\n", a);
        }
    }

Some of the references I have seen talking about using tests for specific values and theories for verifying behavior. As an example, if you have a class that has methods to add and subtract from an attribute, a test would verify correctness of the result (e.g., 1+3 returns 4) whereas a theory might verify that, for the datapoint values (x1, y1), (x2, y2), x+y-y always equals x, x-y+y always equals x, x*y/y always equals x, etc. This way, the results of theories are not coupled as tightly with the data. With theories, you also can filter out cases such as y == 0; they don't count as failure. Bottom line: you can use both. A good paper is: http://web.archive.org/web/20110608210825/http://shareandenjoy.saff.net/tdd-specifications.pdf

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!