Всем привет!
Надеюсь все уже перешли на JUnit 5?
У JUnit 5 много крутых фич по сравнению с 4-й версией, например:
1) более удобная работа с параметризованными тестами через @ParametrizedTest, который вешается на метод - можно миксовать параметризированные и непараметризированные тесты в одном тестовом классе
2) возможность параметризировать не только входные параметры, но и все остальное в тесте с помощью динамически генерируемых тестов DynamicTests https://www.baeldung.com/junit5-dynamic-tests
3) есть возможность проверки исключений и таймаута через методы - assertThrows и assertTimeout. Это более правильно - assert идет после Act (я про Arrange-Act-Assert) и позволяет делать несколько проверок в одном тестовом методе
4) условное выполнение тестов в зависимости от среды: @EnabledOnOs, @EnabledOnJre, @EnabledIfSystemProperty, @EnabledIfEnvironmentVariable, также можно создавать свои условия
5) @RepeatedTest для повтора теста N раз
6) @DisplayName - полезно для задания говорящего имени теста для параметризированных тестов, к примеру
7) @Nested для складывания тестовых классов в "матрешку". Полезно, если у часть тестов нужно выполнить отнаследовавшись от базового класса
8) assertAll - объединение нескольких assert-ов в тесте. Полезно, как способ отключить fail fast режим проверок в JUnit - прогнать все assert-ы в тесте несмотря на падение одного из них.
9) ну и наконец механизм extensions. В 4-й версии был механизм Runner-ов, но его ограничение состояло в том, что на класс можно было повесить один Runner. А extensions может быть сколько угодно. Вот пример реализации BDD с помощью extension https://www.infoq.com/articles/deep-dive-junit5-extensions/ Здесь же есть пример 3-го способа параметризации теста - через ParameterResolver.
10) кроме всего прочего механизм extension добавляет store - контекст для обмена данными между тестами. Важно: для модульных тестов это антипаттерн, но нормально для интеграционных https://junit.org/junit5/docs/5.0.0/api/org/junit/jupiter/api/extension/ExtensionContext.Store.html
11) указание очередности тестов через @Order - полезно для тестирования отдельных шагов в интеграционном тесте. По умолчанию, кстати, тесты запускаются в алфавитном порядке https://www.baeldung.com/junit-5-test-order
В общем JUnit 5 догнал и перегнал TestNG, рекомендую к использованию если еще не пробовали.
#junit #unittests
Надеюсь все уже перешли на JUnit 5?
У JUnit 5 много крутых фич по сравнению с 4-й версией, например:
1) более удобная работа с параметризованными тестами через @ParametrizedTest, который вешается на метод - можно миксовать параметризированные и непараметризированные тесты в одном тестовом классе
2) возможность параметризировать не только входные параметры, но и все остальное в тесте с помощью динамически генерируемых тестов DynamicTests https://www.baeldung.com/junit5-dynamic-tests
3) есть возможность проверки исключений и таймаута через методы - assertThrows и assertTimeout. Это более правильно - assert идет после Act (я про Arrange-Act-Assert) и позволяет делать несколько проверок в одном тестовом методе
4) условное выполнение тестов в зависимости от среды: @EnabledOnOs, @EnabledOnJre, @EnabledIfSystemProperty, @EnabledIfEnvironmentVariable, также можно создавать свои условия
5) @RepeatedTest для повтора теста N раз
6) @DisplayName - полезно для задания говорящего имени теста для параметризированных тестов, к примеру
7) @Nested для складывания тестовых классов в "матрешку". Полезно, если у часть тестов нужно выполнить отнаследовавшись от базового класса
8) assertAll - объединение нескольких assert-ов в тесте. Полезно, как способ отключить fail fast режим проверок в JUnit - прогнать все assert-ы в тесте несмотря на падение одного из них.
9) ну и наконец механизм extensions. В 4-й версии был механизм Runner-ов, но его ограничение состояло в том, что на класс можно было повесить один Runner. А extensions может быть сколько угодно. Вот пример реализации BDD с помощью extension https://www.infoq.com/articles/deep-dive-junit5-extensions/ Здесь же есть пример 3-го способа параметризации теста - через ParameterResolver.
10) кроме всего прочего механизм extension добавляет store - контекст для обмена данными между тестами. Важно: для модульных тестов это антипаттерн, но нормально для интеграционных https://junit.org/junit5/docs/5.0.0/api/org/junit/jupiter/api/extension/ExtensionContext.Store.html
11) указание очередности тестов через @Order - полезно для тестирования отдельных шагов в интеграционном тесте. По умолчанию, кстати, тесты запускаются в алфавитном порядке https://www.baeldung.com/junit-5-test-order
В общем JUnit 5 догнал и перегнал TestNG, рекомендую к использованию если еще не пробовали.
#junit #unittests
Baeldung
Guide to Dynamic Tests in Junit 5 | Baeldung
Learn about dynamic tests introduced in JUnit 5 - a new programming model that supports full test lifecycle.
Всем привет!
Продолжим про антипаттерны в unit тестах.
Мы можем проверить в тесте метод на то, что он выбрасывает исключение.
В JUnit 5:
assertThrows(MyException.class, () -> myObject.myFunction(myString), "Expected myFunction() to throw, but it didn't");
и с помощью AssertJ:
assertThatExceptionOfType(MyException.class)
.isThrownBy(() -> { myObject.myFunction(myString); })
.withMessage("%s!", "boom")
.withMessageContaining("boom")
.withNoCause();
Это хорошая проверка, т.к. всегда нужно убедится, что выброшено именно то исключение, которое мы ожидаем. А иногда требуется проверить его параметры.
Но есть еще методы проверки, что исключения не было.
В JUnit 5:
assertDoesNotThrow(() -> myObject.myFunction(myString));
и AssertJ:
assertThatNoException()
.isThrownBy(() -> myObject.myFunction(myString));
А вот эти проверки выглядят излишними, т.к. выбрасывание исключения в любом случае прерывает тест, и он подсвечивается красным.
Возможно, если тест сложный и в нем много проверок - хочется локализовать место ошибки. Но в этом случае я бы задумался про разделение теста на несколько вместо использования assertDoesNotThrow. Опять же, в противном случае придется использовать данную проверку во всех тестах, кроме тех, что выбрасывают исключение. А это IMHO "замусоривает" код.
P.S. Интересный момент - библиотека Truth, о которой я писал ранее https://t.me/javaKotlinDevOps/51, вообще не содержит методов проверки на выбрасывание исключения, предлагая пользоваться соответствующим методом из JUnit, ведь assertThrows, описанный ранее, возвращает исключение:
val exception = assertThrows(MyException.class, () -> myObject.myFunction());
А уже его можно проверить более детально:
assertThat(exception)
.hasCauseThat()
.isInstanceOf(NumberFormatException.class);
assertThat(exception)
.hasMessageThat()
.startsWith("Bad");
Мне этот подход нравится.
#unittests #junit #assertj #truth #antipatterns
Продолжим про антипаттерны в unit тестах.
Мы можем проверить в тесте метод на то, что он выбрасывает исключение.
В JUnit 5:
assertThrows(MyException.class, () -> myObject.myFunction(myString), "Expected myFunction() to throw, but it didn't");
и с помощью AssertJ:
assertThatExceptionOfType(MyException.class)
.isThrownBy(() -> { myObject.myFunction(myString); })
.withMessage("%s!", "boom")
.withMessageContaining("boom")
.withNoCause();
Это хорошая проверка, т.к. всегда нужно убедится, что выброшено именно то исключение, которое мы ожидаем. А иногда требуется проверить его параметры.
Но есть еще методы проверки, что исключения не было.
В JUnit 5:
assertDoesNotThrow(() -> myObject.myFunction(myString));
и AssertJ:
assertThatNoException()
.isThrownBy(() -> myObject.myFunction(myString));
А вот эти проверки выглядят излишними, т.к. выбрасывание исключения в любом случае прерывает тест, и он подсвечивается красным.
Возможно, если тест сложный и в нем много проверок - хочется локализовать место ошибки. Но в этом случае я бы задумался про разделение теста на несколько вместо использования assertDoesNotThrow. Опять же, в противном случае придется использовать данную проверку во всех тестах, кроме тех, что выбрасывают исключение. А это IMHO "замусоривает" код.
P.S. Интересный момент - библиотека Truth, о которой я писал ранее https://t.me/javaKotlinDevOps/51, вообще не содержит методов проверки на выбрасывание исключения, предлагая пользоваться соответствующим методом из JUnit, ведь assertThrows, описанный ранее, возвращает исключение:
val exception = assertThrows(MyException.class, () -> myObject.myFunction());
А уже его можно проверить более детально:
assertThat(exception)
.hasCauseThat()
.isInstanceOf(NumberFormatException.class);
assertThat(exception)
.hasMessageThat()
.startsWith("Bad");
Мне этот подход нравится.
#unittests #junit #assertj #truth #antipatterns
Telegram
(java || kotlin) && devOps
Всем привет!
Не JUnit-ом единым...
Если говорить о фреймворках для unit тестирования все наверняка вспомнят JUnit и Mockito. Но есть ещё много чего полезного в этой области. Сегодня расскажу про библиотеки для улучшения читаемости проверок - assert. Про…
Не JUnit-ом единым...
Если говорить о фреймворках для unit тестирования все наверняка вспомнят JUnit и Mockito. Но есть ещё много чего полезного в этой области. Сегодня расскажу про библиотеки для улучшения читаемости проверок - assert. Про…