API тестирования, который возвращает несколько значений с помощью JUnit - PullRequest
2 голосов
/ 05 июня 2011

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

Предположим, я должен проверить API с аргументами arg1, arg2 и arg3 и проверить, появляются ли значения a, b, c в возвращенном наборе. То есть мой тестовый пример выглядит следующим образом:

  • вызовите API с помощью arg1 и проверьте, если a, b, c появляются в возвращенном наборе.
  • вызовите API с помощью arg2 и проверьте, если a, b, c появляются в возвращенном наборе.
  • вызовите API с помощью arg3 и проверьте, если a, b, c появляются в возвращенном наборе.

Как разработать этот контрольный пример с Junit 4? Что делать, если мне нужно добавить arg4? Что если я должен проверить, появляется ли значение d в возвращенном наборе? Могу ли я прочитать список аргументов и ожидаемых значений из конфигурации?

Ответы [ 4 ]

4 голосов
/ 05 июня 2011

Свободные утверждения

Прежде всего, используйте библиотеку FEST-Assertions , чтобы представить приятно выглядящие утверждения с осмысленными сообщениями об ошибках:

assertThat(method(arg1)).containsExactly(a, b, c);
assertThat(method(arg2)).containsExactly(a, b, c);
assertThat(method(arg3)).containsExactly(a, b, c);

Способ BDD

Но я понимаю, что ваш вопрос не о синтаксисе, а о методологии: что делать, если arg4 необходимо протестировать?Ну, если arg1 - arg4 имеют другое семантическое значение, я бы посоветовал вам провести отдельный тест для каждого аргумента. Очень подробный, но также чрезвычайно читаемый (псевдокод):

@Test
public void shouldReturnAbcWhenSomeArgumentUsed() {
  //given
  Object arg = arg1;

  //when
  Set<Object> result = method(arg);

  //then
  assertThat(result).containsExactly(a, b, c);
}

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

Рассмотрите возможность тестирования isEven метода.Я бы порекомендовал следующие тесты:

  • shouldReturnTrueForZero
  • shouldReturnTrueForSmallPositiveEvenNumber
  • shouldReturnTrueForLargePositiveEvenNumber
  • shouldReturnFalseForSmallPositiveOddNumber
  • shouldReturnFalseForLargePositiveOddNumber
  • ... и зеркально отразить тесты для отрицательных чисел

Каждый тест представляет немного отличающийся, хорошо определенный сценарий.С другой стороны, вы могли бы генерировать буквально тысячи shouldReturnFalseWhen227, но какова ценность такого набора тестов, кроме его большого размера?Тестируйте семантически разные аргументы и угловые случаи, точно определяя, какой случай проверяется.

Параметризованный способ

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

@RunWith(value = Parameterized.class)
public class JunitTest6 {

    private Object arg;

    public JunitTest6(Object arg) {
        this.arg = arg;
    }

    @Parameterized.Parameters
    public static Collection<Object[]> data() {
        return Arrays.asList(
                new Object[][]{
                        {arg1},
                        {arg2},
                        {arg3}
                });
    }

    @Test
    public void testMethod() {
        assertThat(method(arg)).containsExcatly(a, b, c);
    }

}

На основе this .

3 голосов
/ 05 июня 2011

С точки зрения методологии:

"Гибкий" способ

Тесты требуют постоянной разработки и рефакторинга, как и производственный код. Также применимы такие принципы, как YAGNI («тебе это не понадобится»). Если сейчас , вам нужно только проверить a, b и c, тогда я бы начал с обычного жестко закодированного модульного теста. Если впоследствии ваши контрольные примеры станут повторяться, то непременно подумайте о том, как их реорганизовать.

Или, может быть, вы уже находитесь на этом этапе, но мне кажется, что этот вопрос не дает достаточно информации, чтобы дать более конкретное предложение о том, как реорганизовать юнит-тесты. Читать тесты из XML? Генерировать данные комбинаторного теста? Параметризованный бегун (согласно @Tomasz)? Возможно, я просто недостаточно хорошо понял вопрос, но заявленная проблема кажется слишком абстрактной.

3 голосов
/ 05 июня 2011

Я обычно обращаюсь к Hamcrest для чего-то вроде этого - это библиотека для декларативного написания "matchers", и она прекрасно работает с JUnit.

Однако этот вопрос о SO указывает на то, что хотя это можно сделать с помощью Hamcrest, более простым способом является просто использование метода containsAll из java.util.Collection. :

ArrayList<Integer> expected = new ArrayList<Integer>();
expected.add(1); expected.add(2); expected.add(3);

assertTrue(actual.containsAll(expected));
1 голос
/ 05 июня 2011

при условии, что вы хотите протестировать метод "method1", который принимает один параметр и возвращает набор, который вы напишите:

Set result = method1(arg1);
assertTrue(result.contains(a));
assertTrue(result.contains(b));
assertTrue(result.contains(c));

Но, возможно, лучше всего сравнить набор непосредственно с ожидаемым значением:

Set expected = new HashSet();
expected.add(a);
expected.add(b);
expected.add(c);

assertEquals(expected, method1(arg1));
assertEquals(expected, method1(arg2));
assertEquals(expected, method1(arg3));

И, конечно, не стесняйтесь использовать циклы, чтобы быть более общими, если это необходимо.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...