Методы тестирования JUnit не могут вернуть значение - PullRequest
1 голос
/ 12 марта 2020

Почему методы тестирования JUnit не могут вернуть значение?

Документация говорит (выделено мое):

Могут быть объявлены методы испытаний и методы жизненного цикла локально в текущем классе тестирования, унаследованном от суперклассов или унаследованном от интерфейсов (см. Интерфейсы тестирования и Методы по умолчанию). Кроме того, методы тестирования и методы жизненного цикла не должны быть абстрактными и не должны возвращать значение .

Почему это принудительно , как это?

Это чисто дизайнерский выбор? Это лучшая практика?

Ответы [ 5 ]

3 голосов
/ 12 марта 2020

В чем причина этого?

Думайте о каждом методе тестирования как о логическом аналоге метода public static void main(String[]) в приложении classi c Java. Должна быть хорошо известная сигнатура метода, чтобы инфраструктура JUnit могла идентифицировать тестовые методы и вызывать их стандартным способом.

Что касается заданных c проектных точек, которые вы запрашиваете:

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

  • Причина, по которой методы не могут возвращать значения, заключается в том, что тестовая среда не сможет сделать ничего полезного с возвращаемым значением. (Было бы невозможно отказаться от какого-либо результата, но какой смысл результата теста, который нельзя использовать?)

Я думал, что мы могли бы использовать повторно один метод испытаний внутри другого.

Если вы хотите повторно использовать код в модульных тестах, вы просто используете обычные методы и другие функции OO Java; например, базовые классы, вспомогательные классы и так далее. Есть несколько ситуаций, когда вам нужен автономный метод тестирования и как «компонент» (если не сказать лучшего слова) другого метода тестирования. И если бы вы сделали, вы могли бы написать что-то вроде этого.

    public void test_xxx() {
        real_test_xxx();
    }

    public int real_test_xxx() {
         ...
    }

    public void test_yyy() {
          ...
          res = real_test_xxx()
          ...
    }

Это чисто дизайнерский выбор? Это лучшая практика?

Есть нет лучших практик !

Это варианты дизайна, основанные на общих требованиях и практичность юнит-тестирования 1 . В частности, требование о том, что авторам модульных тестов НЕ нужно создавать конфигурации, чтобы сообщать тестовой среде, что делать.

Обратите внимание, что TestNG использует аналогичный подход. Если метод TestNG @Test объявлен как возвращающий значение, он не рассматривается как метод тестирования; см Может ли метод испытания возвращают значение в TestNG

1047 * В любом случае, если вы не предлагаете реализовать еще один Java тест рамки, это все спорно. 1049 *

1 - Если бы были веские практические причины для необходимости абстрактных методов тестирования или методов тестирования, возвращающих значения, кто-то бы что-то сделал с этим. Массы (авторов модульных тестов) будут расти и свергать тиранический режим (разработчиков тестовых фреймворков). (Повторение «Мы больше не будем одурачены» от «Кто».)

2 голосов
/ 12 марта 2020

Это чисто дизайнерский выбор?

Да. Теоретически, ничто не мешает исполнителю Junit (компоненту, который выполняет тесты тестового класса) принимать действительный метод тестирования с возвращаемым значением.

Это лучшая практика?

Действительно. Чем больше вы ограничиваете способы указания метода модульного тестирования, тем больше вы гарантируете, что не будет неправильного использования.

Например, посмотрите на этот простой пример, который предполагает, что тестовый метод возвращает значение.
A addFoo() тестовый метод, который утверждает, что метод выполняет то, что ожидается, и также возвращает Foo созданный прибор:

@Test
public Foo addFoo(){
   Foo foo = new Foo(...);

   // call the api ...
   sut.addFoo(foo); 

   // assertion
   assertEquals(...);

   // return the foo fixture
   return foo;
}

А здесь addFooBar() метод тестирования, который извлекает прибор Foo, созданный предыдущим методом, а затем утверждает, что метод addFooBar() делает то, что ожидается:

@Test
public void addFooBar(){
   Foo foo = addFoo();
   Bar bar = new Bar(..., foo);

   // call the api ...
   sut.addFooBar(bar); 

   // assertion
   assertEquals(...);
}

Это вызывает множество проблем:

  • Должен ли метод addFoo() выполняться несколько раз? Это может повлиять на скорость выполнения теста и сделать отчеты об испытаниях неясными.
  • Результат теста addFoo() может привести к сбою результата теста addFooBar(), несмотря на правильную реализацию.
    Как диагностировать c источник проблемы? Мы добавили бесполезную сложность.
  • Результат теста addFoo() может сделать результат теста addFooBar() успешным, несмотря на неправильную реализацию. Действительно, неправильная реализация в addFoo() может компенсировать неправильную реализацию в addFooBar()
2 голосов
/ 12 марта 2020

Одна вещь, о которой я еще не упомянул, это то, что одна из причин этого проектного решения является исторической.

До тестовых случаев, отмеченных аннотациями, они анализировались JUnit с помощью отражения - все public void методы, имя которых начиналось с test и не имело никаких аргументов, считались тестовыми примерами, которые выполнялись фреймворком.

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

В любом случае вы должны были бы сделать их закрытыми Я думаю.

Кроме того, это было также самое время "имени метода, начинающегося с глагола, который должен делать что-то" (а не вычислять что-то).

1 голос
/ 12 марта 2020

Методы испытаний должны выполняться независимо

Если тесты не могут выполняться независимо, то они не являются модульными тестами.

Для модульного теста не следует полагаться в любом внешнем состоянии

Если метод теста вернет значение, может быть применено то, что результаты теста должны использоваться / относиться к другим тестам

Та же самая лучшая практика в TestNG

Поскольку TestNG следует передовым методам для модульного тестирования, это означает, что метод модульного тестирования не должен иметь возвращаемого значения

0 голосов
/ 12 марта 2020

вы можете написать несколько частных методов и использовать их как

@Test
public void test1() {
    privateTest();
}

@Test
public void test2() {
    privateTest();
//    more Logic

}

private int privateTest() {
   return 0;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...