Можно ли вложить JUnit 5 параметризованных тестов? - PullRequest
0 голосов
/ 15 ноября 2018

Я пытаюсь написать параметризованный тест для интерфейса Foo, который объявляет метод getFooEventInt (int, int). Я написал параметризованный тест, который работает для одного экземпляра Foo (объект FooImpl).

public class FooTest {

    @ParameterizedTest
    @MethodSource("getFooEvenIntProvider")
    public void getFooEvenIntTest(int seed, int expectedResult) {
        Foo foo = new FooImpl();

        Assertions.assertEquals(expectedResult, foo.getFooEvenInt(seed));
    }

    private static Stream getFooEvenIntProvider() {
        return Stream.of(
            Arguments.of(-2,  0),
            Arguments.of(-1,  0),
            Arguments.of( 0,  2),
            Arguments.of( 1,  2),
        );
    }
}

Тем не менее, я хотел бы иметь возможность вызывать getFooEvenIntTest (int, int) для предоставленного списка экземпляров реализации Foo, с каждой итерацией, а затем с использованием предоставленного списка значений seed /pectedResult.

Я понимаю, что могу сделать это как ...

public class FooTest {

    @ParameterizedTest
    @MethodSource("getFooProvider")
    public void getFooImplEvenIntTest(Foo foo) {
        int[] expectedResult = {  0,  0, 2, 2 };
        int[] seed           = { -2, -1, 0, 1 };

        for(int i=0; i<seed.length; i++) {
            Assertions.assertEquals(expectedResult[i],
                                    foo.getFooEvenInt(seed[i]));
        }
     }

    private static Stream getFooProvider() {
        return Stream.of(
                Arguments.of(new FooImpl()),
                Arguments.of(new FooImpl2())
        );
    }
}

Есть идеи? Я опубликую, если выясню, но я подумал, что проверю, возможно ли это сделать, или есть другой подход.

Ответы [ 2 ]

0 голосов
/ 28 февраля 2019

Полагаю, вы думаете о комбинировании двух потоков аргументов. Этого можно достичь, создав декартово произведение двух списков аргументов.

Я реализовал это на https://github.com/joerg-pfruender/junit-goodies/blob/master/src/main/java/com/github/joergpfruender/junitgoodies/ParameterizedTestHelper.java

public static Stream<Arguments> cartesian(Stream a, Stream b) {
  List argumentsA = (List) a.collect(Collectors.toList());
  List argumentsB = (List) b.collect(Collectors.toList());

  List<Arguments> result = new ArrayList();
  for (Object o : argumentsA) {
    Object[] objects = asArray(o);
    for (Object o1 : argumentsB) {
      Object[] objects1 = asArray(o1);
      Object[] arguments = ArrayUtils.addAll(objects, objects1);
      result.add(Arguments.of(arguments));
    }
  }
  return result.stream();
}

private static Object[] asArray(Object o) {
  Object[] objects;
  if (o instanceof Arguments) {
    objects = ((Arguments) o).get();
  } else {
    objects = new Object[]{o};
  }
  return objects;
}

Тогда ваш тестовый код будет:

  public static Stream<Arguments> fooIntsAndFooProvider() {
    return ParameterizedTestHelper.cartesian(getFooEvenIntProvider(), getFooProvider());
  }

  @ParameterizedTest
  @MethodSource("fooIntsAndFooProvider")
  public void getFooImplEvenIntTest(Integer seed, Integer expectedResult, Foo foo) {
        Assertions.assertEquals(expectedResult,
                                foo.getFooEvenInt(seed));
  }
0 голосов
/ 21 ноября 2018

BLUF: я буду интерпретировать сверчки как «даже если бы вы могли, вы не должны вкладывать параметризованные тесты», и в этом случае я запускаю с подходом, описанным ниже.

Для интерфейса Foo ...

public interface Foo {
    public char getFirstChar(String strValue);
    public int  getNextEvenInt(int seed);
}

«Лучшее» использование параметризованных тестов для реализаций Foo будет ...

public class FooTest {

    @ParameterizedTest
    @MethodSource("getFooProvider")
    public void getFirstCharTest(Foo foo) {
        char[]   expectedResult = { 'a', 'b', 'c', 'd' };
        String[] seed           = { "alpha", "bravo", "charlie", "delta" };

        for(int i=0; i<seed.length; i++) {
            Assertions.assertEquals(expectedResult[i],
                                    foo.getFirstChar(seed[i]));
        }
    }

    @ParameterizedTest
    @MethodSource("getFooProvider")
    public void getNextEvenIntTest(Foo foo) {
        int[] expectedResult = {  0,  0, 2, 2 };
        int[] seed           = { -2, -1, 0, 1 };

        for(int i=0; i<seed.length; i++) {
            Assertions.assertEquals(expectedResult[i],
                                    foo.getFooEvenInt(seed[i]));
        }
    }

    private static Stream getFooProvider() {
        return Stream.of(
                Arguments.of(new FooImplOne()),
                Arguments.of(new FooImplTwo())
                // extend as need for implementations of Foo
        );
    }
}

ПокаЯ не получу «теплых размышлений» от просмотра результатов прохождения для каждой пары значений в различных тестах, это выполнит мою цель иметь тест на уровне интерфейса, который я могу легко расширить для проверки / проверки реализаций интерфейса.

...