(java || kotlin) && devOps
363 subscribers
6 photos
1 video
7 files
337 links
Полезное про Java и Kotlin - фреймворки, паттерны, тесты, тонкости JVM. Немного архитектуры. И DevOps, куда без него
Download Telegram
Всем привет!
Не JUnit-ом единым...
Если говорить о фреймворках для unit тестирования все наверняка вспомнят JUnit и Mockito. Но есть ещё много чего полезного в этой области. Сегодня расскажу про библиотеки для улучшения читаемости проверок - assert. Про важность читаемости кода, в т.ч тестового я уже писал.
Пример для затравки из AssertJ
assertThat(testList).hasSize(2)     .containsExactly("index3", "index4")     .isUnmodifiable();
Больше примеров см по ссылкам в конце поста.
Библиотек три.
1) Hamcrest. Старичок, родоначальник жанра, уже не развивается, не рекомендуется к использованию
2) AssertJ - в отличие от hamcrest построен на принципе method chaining, что позволяет использовать автопополнение IDE и выглядит более читаемо. Выводит более понятное сообщение об ошибке, что тоже важно. Есть фича Soft Assertion, позволяющая лениво описать n проверок и выполнить их за раз.
3) Truth - очень похож по принципу работы - method chaining - на AssertJ, при этом менее известен. В качестве преимущества его разработчики указывают более компактное API и более понятное логирование ошибок.
Как AssertJ, так и Truth позволяют создавать свои проверки.
За деталями предлагаю пойти сюда:
https://dzone.com/articles/hamcrest-vs-assertj-assertion-frameworks-which-one

https://habr.com/ru/post/675778/

https://truth.dev/comparison.html
#unittests #rare_test_libs
👍2
Всем привет!

Давно хотел написать про паттерны/шаблоны программирования. Основной вопрос, возникающий при разговоре про паттерны - какая от них польза? Ведь главное - умеет человек кодить или нет.
С одной стороны паттерны - это лишь часть арсенала программиста. Можно заучить все паттерны, но не научиться кодить.
И тут возникает второй вопрос - о каких паттернах мы говорим?
1) самые известные - паттерны проектирования из книги «банды четырёх» https://refactoring.guru/ru/design-patterns/catalog
Это синглтон, фабричный метод, билдер и все все все
2) паттерны Enterprise архитектуры от Фаулера https://martinfowler.com/eaaCatalog/
3) паттерны рефакторинга https://refactoring.com/catalog/ Про них также говорится в книге Идеальная работа Мартина
4) паттерны модульных тестов http://xunitpatterns.com/ и снова в книге Идеальная работа
5) паттерны интеграции корпоративных приложений https://www.enterpriseintegrationpatterns.com/patterns/messaging/toc.html многие из которых можно встретить в стандарте JMS
6) паттерны микросервисных приложений https://microservices.io/patterns/index.html
7) даже у Kubernates есть паттерны https://www.redhat.com/cms/managed-files/cm-oreilly-kubernetes-patterns-ebook-f19824-201910-en.pdf
8) не говоря уже про антипаттерны https://javarush.ru/groups/posts/2622-chto-takoe-antipatternih-razbiraem-primerih-chastjh-1
9) 10) ...
Из этого списка можно сделать вывод, что паттерны могут быть везде. А из этого второй вывод: паттерны - это удобный способ описания какой-то области разработки. Собственно это и есть их ценность. Шаблоны помогают изучить новую технологию, читать статьи, книги и главное читать код и тесты. Ну и проектировать систему, обсуждать ее архитектуру с коллегами. По сути паттерны - это язык проектирования. А идеальный способ их использования - когда они уже реализованы в неком фреймворке: Singleton и MVC в Spring, Builder в Lombok, Sidecar в k8s, или в языке как Singleton и Decorator в Kotlin.

#patterns #refactoring #unittests
👍3
Всем привет!

По следам отличной книги Владимира Хорикова Принципы юнит-тестирования, см https://t.me/javaKotlinDevOps/50, решил погрузится в тему и прочитать еще и классику жанра - Шаблоны тестирования xUnit. Рефакторинг кода тестов https://www.litres.ru/dzherard-mesarosh/shablony-testirovaniya-xunit-refaktoring-koda-t-48637685/
К слову, на английском книга выложена в виде сайта со списком паттернов тестирования http://xunitpatterns.com/
По сути книга и является большим справочников паттернов. Автор - человек дотошный: любую типовую практику, используемую для написания тестов он вынес в шаблон с подробным описанием истории возникнования, вариантов релизации и примеров, мотивирующих на использование шаблонов.
Вот примеры шаблонов из книги, на которые хотел бы обратить внимание:
1) 5 видов моков http://xunitpatterns.com/Mocks,%20Fakes,%20Stubs%20and%20Dummies.html - от Dummy object, который ничего не возвращает, не делает и не проверяет, а нужен лишь для передачи как параметр, до Fake Object - облегченной реализации боевой логики, без обращений во внешние системы и БД. Видел ссылки на эти 5 типов в других статьях и книгах.
2) Test Utility Method - одна из базовых практик при рефаторинге тестов, вынесение повторяющего кода в отдельные методы. Это может быть код настройки системы, код проверки результата с assert-ми и код очистики ресурсов. Очень полезная штука, с какого-то момента после рефакторинга вынесенных методов для их переиспользования мы получаем некий тестовый язык, по сути свой DSL, и это без всяких Cucumber-ов и прочих BDD. http://xunitpatterns.com/Test%20Utility%20Method.html

Остальное не влезло в пост телеги, см. на дзене https://dzen.ru/media/id/62fe543369f7d3314503a87d/recenziia-na-shablony-testirovaniia-xunit-6367bbba7d9dc52b40aa3ff3

#unittests #books
👍1
Всем привет!

Я подозреваю почти все знают и используют такой фреймворк, как Mockito. По крайней мере судя по собеседованиям, которые я провожу и коду, который вижу)
Наверняка все знают mock, spy, when(...).thenAnswer.
Но я хотел бы рассказать про ряд его малоизвестных особенностей:
1) можно создавать тестовые двойники через Mockito.mock или Mockito.spy, а можно воспользоваться аннотациями над полями класса: @Mock и @Spy, главное не забыть вызвать MockitoAnnotations.openMocks(testClass); перед каждым вызовом тестового метода
2) Mockito с версии 2 научился mock-ать final методы и классы
3) Mockito также научился mock-ать static методы. Что ж, PowerMock теперь не нужен) Да, остаются private методы, но во-первых я бы их не тестировал, а во-вторых если очень надо - есть рефлексия
4) через verify можно делать сложные проверки поведения: что методы какого-то класса не вызывались, что вызывались только определенные методы класса и ничего более, сколько раз вызывался метод, с какими аргументами. Здесь главное не переборщить и не сделать тест слишком хрупким. Разделять тестирование бизнес-процесса и детали реализации
5) с помощью ArgumentCaptor можно захватить содержимое передаваемого в mock параметра и проанализировать его отдельными assert-ами. Полезно для сложных объектов или для анализа содержимого строки
6) как известно, двойники, созданные с помощью mock, по умолчанию не возвращают ничего при вызове метода, т.к. вызова не происходит. Можно захардкодить ответ в помощью Mockito.when(...).thenReturn. Но если нужно вернуть значение в зависимости от входных параметров, а настраивать реальный объект не хочется - есть два варианта: создать наследника интерфейса Answer, где в методе answer сформировать ответ, либо сделать то же самое c использованием Streams API и Mockito.when(...).thenAnswer
Когда искал ссылки для поста, нашел отличную статью, где описываются практически все описанные выше лайфхаки: https://habr.com/ru/post/444982
Ну разве что кроме mock static https://www.baeldung.com/mockito-mock-static-methods и возврата сложного ответа из mock при помощи Answer https://www.baeldung.com/mockito-mock-methods

Пост будет дополняться полезными фичами по мере их нахождения)
Как говорить читать не перечитать https://www.javadoc.io/doc/org.mockito/mockito-core/latest/org/mockito/Mockito.html
Stay tuned)

#unittests #mockito
👍5
Всем привет!

Надеюсь все уже перешли на 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
👍2