
Во вступительном видео нового курса поговорим про то, что такое тестирование программного обеспечения, какие виды его бывают, что такое регрессионное и функциональное тестирование. И конечно же поговорим об основном фреймворке, который чаще всего используется в Java приложениях и который будет изучаться на протяжении всего этого курса - JUnit 5.
00:00 - Введение
00:21 - Тестирование ПО
01:14 - Регрессионное тестирование
01:52 - Unit testing
02:29 - Integration testing
03:11 - Acceptance testing
04:02 - Диаграмма всех видов тестирования
05:09 - JUnit 5
07:24 - Резюме
Перед тем, как переходить к непосредственно изучению фреймворка JUnit 5, нам необходимо установить соответствующее программное обеспечение. Более того, рассмотрим варианты настройки для обоих build инструментов: Apache Maven и Gradle. К счастью, нам не придется устанавливать их, потому что существуют так называемые wrapper как для Maven, так и для Gradle.
Ссылка на код с занятия: https://github.com/dmdev2020/junit5-maven-starter/tree/lesson-2
Ссылка на maven-wrapper: https://github.com/takari/maven-wrapper
Ссылка для скачивания IntelliJ IDEA: https://www.jetbrains.com/idea/download/
Ссылка для скачивания Java 16: https://www.oracle.com/java/technologies/javase-jdk16-downloads.html
00:00 - Введение 00:14 - Установка Java 16
00:45 - Установка и запуск IntelliJ IDEA
02:07 - Настройка Gradle и JUnit 5
04:41 - Gradle wrapper
05:41 - Настройка Apache Maven и JUnit 5
08:43 - Apache Maven wrapper
На занятии мы напишем наш первый тест, разберемся с аннотацией @Test и утилитным классом Assertions, обсудим конвенцию именования методов и классов. Начнем обсуждать отличия JUnit 5 от предыдущей версии JUnit 4
Ссылка на код с занятия: https://github.com/dmdev2020/junit5-maven-starter/tree/lesson-3
00:00 - Введение
00:18 - Пакеты и именование тест классов
01:50 - Аннотация @Test
03:24 - Создание класса UserService
04:50 - Именование тестовых методов
06:25 - Класс Assertions
На видео разберем жизненный цикл тестов, ведь на самом деле у нас есть еще 4 основных аннотации кроме @Test: @BeforeAll, @BeforeEach, @AfterEach и @AfterAll. Узнаем все нюансы их использования, а также для чего используется аннотация @TestInstance.
Ссылка на код с занятия: https://github.com/dmdev2020/junit5-maven-starter/tree/lesson-4
00:00 - Введение
00:21 - Жизненный цикл тестов
02:00 - Тест на проверку количества пользователей
04:30 - Аннотации @BeforeEach и @AfterEach
07:18 - Аннотации @BeforeAll и @AfterAll
08:30 - Аннотация @TestInstance
Мы видели на предыдущих занятиях, что IntelliJ IDEA позволяет нам запускать тесты, как будто мы запускаем метод main. То же самое и с Maven/Gradle - оба инструмента умеют запускать наши тесты. Теперь мы разберемся, как именно они это делают, подробно изучая архитектуру JUnit 5 и слой Launcher API в нем.
Ссылка на код с занятия: https://github.com/dmdev2020/junit5-maven-starter/tree/lesson-5
00:00 - Введение
00:31 - Архитектура JUnit 5
03:15 - Написание своего Test Launcher
07:18 - Интерфейс TestExecutionListener
09:34 - Исходники platform-launcher и jupiter-engine
На предыдущих занятиях мы уже говорили немного про такую аббревиатуру как TDD. Теперь настал момент остановиться и более подробно разобраться в этом, в чем суть такой методологии и какие плюсы можем извлечь из этого. Как обычно все рассмотрим на практике и в последующих видео будем закреплять.
Ссылка на код с занятия: https://github.com/dmdev2020/junit5-maven-starter/tree/lesson-6
00:00 - Введение
00:18 - TDD flow
01:48 - Книга "Программист прагматик"
02:12 - RED - GREEN - REFACTOR
02:50 - Практика TDD
09:55 - Резюме
Как мы и обсуждали в предыдущих видео, JUnit 5 разбит на модули, что позволяет нам подключать только то, что нам необходимо. Поэтому для обогащения функциональности Assertions, мы можем использовать такие библиотеки как AssetJ и Hamcrest, что и продемонстрируем в этом видео.
Ссылка на код с занятия: https://github.com/dmdev2020/junit5-maven-starter/tree/lesson-7
00:00 - Введение
00:35 - AssertJ. assertThat функциональность
03:21 - AssertJ. Тестирование коллекций
07:02 - Подключение зависимости Hamcrest
08:23 - Hamcrest. Тестирование коллекций
Довольно часто нам приходится работать в коде с исключениями (наследники класса Throwable). И конечно же это отдельный test case, который требует покрытия. К счастью, в JUnit 5 есть прекрасный функционал для таких случаев. Разберем на видео как бы мы делали такие проверки без специальных exception asserts и с ними.
Ссылка на код с занятия: https://github.com/dmdev2020/junit5-maven-starter/tree/lesson-8
00:00 - Введение
00:25 - Старый вариант тестирования исключений
03:17 - assertThrows
04:58 - Тестирование исключений в JUnit 4
07:08 - Run tests with Coverage
JUnit 5 привнес нам много новых аннотаций. И одна из самых полезных из них - это @Tag, которая позволяет запускать и отфильтровывать только нужные нам тесты (особенно эффективно для Integration и Acceptance тестов). На видео посмотрим, как это делает IntelliJ IDEA или любой build tools, а потом попрактикуемся сами.
Ссылка на код с занятия: https://github.com/dmdev2020/junit5-maven-starter/tree/lesson-9
00:00 - Введение
00:16 - Аннотация @Tag
02:16 - Запуск tagged тестов через Launch API
03:23 - Запуск tagged тестов через Maven
04:17 - Запуск tagged тестов через Gradle
04:31 - Эффект @Tag над классом
Порядок тестов не должен быть важен, как мы и обсуждали на предыдущих занятиях. Даже есть такие chain gang anti-pattern, который как раз-таки и описывают такую зависимость. Тем не менее, в JUnit 5 есть возможность указать порядок следования тестов. Поговорим, как это реализовано, а также, как улучшить читаемость названий наших тестов через такие аннотации как @DisplayName и @Nested.
Ссылка на код с занятия: https://github.com/dmdev2020/junit5-maven-starter/tree/lesson-10
00:00 - Введение
00:57 - Аннотация @TestMethodOrder
01:26 - Random tests order
02:02 - Аннотация @Order
02:47 - MethodName tests order
03:12 - DisplayName tests order. Аннотация @DisplayName
04:44 - Аннотация @Nested
Dependency Injection (DI) - это паттерн проектирования, суть которого в том, что есть отдельный объект, который отвечает за обеспечивание зависимостями другие объекты. Он широко используется в фреймворками, особенно такими как Spring. Также и JUnit 5 имеет подобный функционал, предоставляющий новые возможности в тестировании, например, параметризованные тесты и другое. На видео попробуем более подробно разобраться в нем.
Ссылка на код с занятия: https://github.com/dmdev2020/junit5-maven-starter/tree/lesson-11
00:00 - Введение
00:13 - Определение Dependency Injection
01:14 - Параметры в конструкторах и методах test класса
02:51 - Интерфейс ParameterResolver
03:49 - Создание класса UserServiceParamResolver
08:35 - Интерфейс Store
12:01 - Резюме
Как и обсуждали на предыдущем видео, Dependency Injection (DI) предоставил довольно много приятных возможностей в JUnit 5. И одно из них - это параметризованные тесты, которые невероятно удобны и довольно часто используются на практике. На видео подробно обсудим эту тему.
Ссылка на код с занятия: https://github.com/dmdev2020/junit5-maven-starter/tree/lesson-12
00:00 - Введение
00:25 - Зависимость junit-jupiter-params и @ParameterizedTest
02:10 - Аннотация @ArgumentsSource
03:52 - Аннотации @NullSource, @EmptySource, @NullAndEmptySource
06:18 - Аннотации @ValueSource, @EnumSource
07:35 - Аннотация @MethodSource
12:06 - CSV формат данных
14:01 - Аннотации @CsvFileSource, @CsvSource
16:23 - Именование parameterized tests
Flaky tests - это такие тесты, которые не воспроизводят один и тот же результат при передаче одних и тех же параметров, другими словами говоря, они являются нестабильными. Для того, чтобы избавиться от таких тестов или по крайней мере уменьшить их количество, в JUnit 5 есть несколько способов. На занятии обсудим каждый из них, а также затронем тему таймаутов и времени выполнения тестов, которое особенно важно в Integration и Acceptance тестировании.
Ссылка на код с занятия: https://github.com/dmdev2020/junit5-maven-starter/tree/lesson-13
00:00 - Введение
00:15 - Flaky tests
01:15 - Аннотация @Disabled
02:02 - Аннотация @RepeatedTest
04:29 - assertTimeout
06:34 - assertTimeoutPreemptively
08:13 - Аннотация @Timeout
Для того, чтобы изменить жизненный цикл тестов или внести коррективы в какой-то фазе, на каком-то событии, можно воспользоваться новый средством, которое появилось в JUnit 5 - это extension model. Она пришла на замену старым возможностям JUnit 4, вроде аннотаций @RunWith или @Rule. Поговорим в видео более подробно почему это произошло, зачем пришлось полностью отказаться от старых возможностей и т.д.
Ссылка на код с занятия: https://github.com/dmdev2020/junit5-maven-starter/tree/lesson-14
00:00 - Введение
00:22 - Старые аннотации @RunWith и @Rule
02:02 - Extension Model
04:47 - Аннотация @ExtendWith
05:43 - Класс ExtensionContext
07:14 - Основные интерфейсы Extension
08:29 - Резюме
На предыдущем занятии мы познакомились с 5-ю основными расширениями. И теперь, зная теоретический материал и то, что мы уже работали с одним из расширений на лекции по Dependency Injection, мы попрактикуемся с каждым из них и посмотрим все возможности в JUnit 5.
Ссылка на код с занятия: https://github.com/dmdev2020/junit5-maven-starter/tree/lesson-15
00:00 - Введение
00:20 - Test life cycle callback
04:19 - Наследование в тестовых классах
05:40 - Test instance post-processing
08:40 - Conditional test execution
11:55 - Exception handling
14:10 - Резюме
До текущего момента, мы писать unit тесты, опираясь лишь на один класс UserService, который не зависел ни от каких других классов. На практике же, такое встречается очень редко. Поэтому, если бы продолжим писать наши тесты с зависимостями на другие классы, то это уже будут integration тесты, где мы проверяем не только функционал отдельно взятой функции, но и интеграцию друг с другом нескольких классов. Чтобы этого избежать и продолжить писать именно unit тесты, нам необходимо познакомиться с таким фреймворком как Mockito. На видео начнем разбираться в теории про mock объектов и такое понятие как Test Doubles.
Ссылка на код с занятия: https://github.com/dmdev2020/junit5-maven-starter/tree/lesson-16
00:00 - Введение
01:05 - Зачем нужен Mockito
01:54 - Test Doubles
02:26 - Dummy objects
03:08 - Fake objects
03:48 - Stub objects
04:22 - Mock objects
05:00 - Spy objects
05:38 - Подключение зависимости mockito-core
На первом практическом занятии по фреймворку Mockito мы сразу же познакомимся с основным утилитным классом Mockito, который является отправной точкой при работе с ним. Конечно же поработаем с самым часто используемым из Test Doubles - это Mock. Попробуем сами реализовать такой класс, чтобы лучше разобраться в нем. На протяжении всего видео также обговорим, что такое Dummy, Fake и Stubs объекты.
Ссылка на код с занятия: https://github.com/dmdev2020/junit5-maven-starter/tree/lesson-17
00:00 - Введение
00:24 - Добавление UserDao
02:59 - Mockito.mock
05:45 - Устройство Mock объекта
07:37 - Первый вариант создания Stubs
09:40 - Устройство Stub объекта
13:15 - Второй вариант создания Stubs
Следующий очень важный Test Double - это Spy. Как и на прошлом видео, попробуем сами реализовать его, чтобы лучше разобраться в Spy. Также пройдем по другим методам утилитного класса Mockito и познакомимся с таким очень полезным классом как ArgumentCaptor, который позволяет нам перехватывать переданные аргументы в методы mocks и spies во время выполнения.
Ссылка на код с занятия: https://github.com/dmdev2020/junit5-maven-starter/tree/lesson-18
00:00 - Введение
00:53 - Устройство Spy объекты
02:23 - Mockito.spy
03:46 - Методы класса Mockito
05:10 - Метод verify
07:28 - Класс ArgumentCaptor
Используя гибкую возможность расширений (extensions), которая появилась в JUnit 5, мы можем еще упростить использование Mockito и создавать Mock, Spy, Captor в декларативном стиле, т.е. через аннотации. Для этого нам придется подключить еще одну зависимость. На видео более подробно разберемся с новой для нас информацией и также затронем тему static mocks, и почему не стоит их использовать.
Ссылка на код с занятия: https://github.com/dmdev2020/junit5-maven-starter/tree/lesson-19
00:00 - Введение
00:24 - Подключение зависимости mockito-junit-jupiter
00:47 - MockitoExtension
02:13 - Аннотации @Mock, @Spy, @InjectMocks, @Captor
05:25 - Strictness
08:25 - Lenient mocks
10:01 - Mock static
10:58 - Резюме
На одной из первых лекций курса по JUnit 5 мы с вами познакомились с такой аббревиатурой как TDD (Test Driven Development). Но есть еще одна, которая чаще используется именно при написании acceptance тестов, и основывается на таком же принципе: сначала пишутся тесты, а затем основной функционал. Речь сейчас идет о BDD - Behavior Driven Development, про которую и пойдет речь в этом видео.
Ссылка на код с занятия: https://github.com/dmdev2020/junit5-maven-starter/tree/lesson-20
00:00 - Введение
00:21 - Аббревиатура BDD
01:20 - given-when-then
02:55 - Story & Scenario
03:38 - JBehave
05:11 - BDDMockito
06:35 - Резюме
На заключительном практическом занятии по JUnit 5 мы попрактикуемся в написании unit и integration тестов для мини проекта на Java Core, чтобы закрепить весь пройденный материал на практике.
00:00:00 - Введение
00:00:30 - Структура проекта
00:04:01 - LocalDateFormatter unit test
00:10:30 - PropertiesUtil unit test
00:13:05 - CreateUserValidator unit test
00:21:35 - CreateUserMapper unit test
00:25:41 - UserService unit test (method login)
00:35:07 - UserService unit test (method create)
00:41:39 - UserDao integration test
00:55:57 - UserService integration test
01:01:16 - Проверка покрытия классов тестами
01:03:23 - Резюме
В заключительном видео поговорим про то, что мы знаем на текущий момент, какие темы мы еще не покрыли в данном курсе. Какие книги нужны почитать для того, чтобы углубиться в тему тестирования программного обеспечения с использованием JUnit 5.
Ссылка на официальную документацию JUnit 5: https://junit.org/junit5/docs/current/user-guide/#overview
00:00 - Введение
01:41 - JUnit 5 в Spring framework
03:00 - JUnit 5 documentation
04:37 - Книга "Java Unit Testing with JUnit 5"
Курс JUnit 5 включает в себя не только практическую часть, но и теорию тестирования, т.е. содержит информацию про основные понятия и определения в тестировании программного обеспечения, такие как:
- все виды тестов (unit, integration, acceptance)
- регрессионное и функциональное тестирование
- flaky тесты
- различные методологии и подходы в разработке программного обеспечения (TDD, BDD)
- жизненный цикл тестов
- многое другое
Также подробно будет разобран фреймворк Mockito, без которого не обходится ни один проект. Более того, он активно используется в таком фреймворке как Spring. Следовательно, знание его обязательно для любого Java разработчика.
Для кого-то будет полезно узнать про механизм внедрения зависимостей (Dependency Injection - DI), т.к. в JUnit 5 он также был реализован для получения огромной гибкости в тестовых классах и методах, которые мы также разберем в теории и практике. Даже если вы не знакомы с DI - он все равно будет подробно разобран с самого нуля.
Будут отдельные видео, которые раскроют мощь новой Extension модели, которая в свою очередь пришла на замену устаревших подходов в JUnit 4: runners и rules. Благодаря чему мы можем внедряться на любом этапе жизненного цикла тестов.
Ну и Конечно же речь будет идти про основной инструмент, который используется для тестирования программного обеспечения в Java - это фреймворк JUnit 5.
По окончании курса вы будете понимать, что из себя представляет тестирование ПО, уверенно владеть фреймворком JUnit 5 и хорошо разбираться во всех его аспектах.