От Зефира в коробке к Structure Zephyr или как тест-менеджеру перекроить внут...
Let's Talk About Junit 5
1. Software quality assurance days
21 Международная конференция
по вопросам качества ПО
sqadays.com
Москва. 26–27 мая 2017
Соковец Артем
Сбербанк-Технологии, Санкт-Петербург, Россия
2.
3. Let's Talk About Junit 5
О себе
Артем Соковец
Менеджер направления Research and Development
AVSokovets.SBT@sberbank.ru
5. Let's Talk About Junit 5
Содержание
Roadmap
Архитектура
Обзор нововведений
Extension Points
TestNG vs Junit 5
Setup
Top User Questions
Итоги
6. Let's Talk About Junit 5
RoadMap Junit 5
Phase 0: Crowdfunding Campaign
Phase 1: Kickoff Meeting -> 22.10.2015
Phase 2: The Prototype -> 02.12.2015
Phase 3: Heading for an Alpha -> 01.02.2016
Phase 4: Working Toward a First Milestone -> 07.07.2016
Phase 5: Additional Milestones -> (M4) 01.04.2017
Phase 6: Release Candidates
Phase 7: GA Release
Q3 2017
Ответственные
Johannes Link и
Marc Philipp
7. Let's Talk About Junit 5
Архитектура
JUnit 5 = Platform + Jupiter + Vintage
Platform
Vintage Jupiter
Старые
тесты
Новые
тесты
Third Party
IDEs/Build
Tools
TestNG,
Spock,
Cucumber
8. Let's Talk About Junit 5
Нововведение: #1
Изменились имена аннотаций жизненного цикла
Junit 5Junit 5 Junit 4Junit 4
@BeforeAll
static void beforeAll(){}
@BeforeEach
void beforeEach() {}
@AfterEach
void afterEach() {}
@AfterAll
static void afterAll() {}
@BeforeClass
public static void beforeClass() {}
@Before
public void before() {}
@After
public void after() {}
@AfterClass
public static void afterClass () {}
14. Let's Talk About Junit 5
Результат выполнения
org.opentest4j.MultipleFailuresError: numbers (2 failures)
expected: <0> but was: <1>
expected: <4> but was: <1>
org.opentest4j.MultipleFailuresError: numbers (2 failures)
expected: <0> but was: <1>
expected: <4> but was: <1>
Вывод при ошибке:
15. @Test
void test(TestInfo tInfo) {
log.info(tInfo.getDisplayName());
}
Let's Talk About Junit 5
Нововведение: #5
Внедрение параметров в тестовые методы и в
конструкторы тестового класса.
@Rule
public TestName testName
= new TestName();
@Test
public void test() {
log.info(
testName.getMethodName());
}
@Test
void test1(TestReporter tReport) {
tReport.publishEntry
("SQADAYS", “true 100%");
}
Junit 5Junit 5 Junit 4Junit 4
16. Let's Talk About Junit 5
Нововведение: #6
Более детальная информация об исключении
17. Let's Talk About Junit 5
Нововведение: #7
@DisplayName("СББОЛ TK API - Отправка писем в банк")
public class BDDStyleTest {
@Test
@DisplayName("Дано пользователь авторизовался в систему")
void login() { /*...*/ }
@Test
@DisplayName("Когда пользователь отправляет сообщение")
void sendMess() { /*...*/ }
@Nested
@DisplayName("Тогда система присылает ответ")
class AfterSending {
@Test
@DisplayName("идентификатор уникальный")
void checkTicket() { /*...*/ }
@Test
@DisplayName("идентификатор заполнен корректно")
void checkTicketField() { /*...*/ }
}
}
Организуемые и легкочитаемые тесты
18. Let's Talk About Junit 5
Результат выполнения
Результаты теста с использованием
@Nested и @Display в IDEA
19. Let's Talk About Junit 5
Нововведение: #8
Обновленные параметризированные возможности
@RunWith(value =
Parameterized.class)
public class HelloTest {
//Параметры и конструктор
@Parameterized.Parameters
public static Collection<Object[]>
data() {return asList(
new Object[][]{{1}});
}
@Test
public void compareTest() {
assertTrue(numberA > 0);}}
@ParameterizedTest
@ValueSource(ints = {1, 2, 3})
void valueSource(int arg) {
assertTrue(arg > 0);
}
Junit 5Junit 5 Junit 4Junit 4
@ParameterizedTest
@MethodSource(names = "dProvider")
void methodSource(String arg) {
assertNotNull(arg);}
@ParameterizedTest
@CsvFileSource(resources =“.csv")
//Code
@ParameterizedTest
@ArgumentsSource(Provider.class)
//Code
21. Let's Talk About Junit 5
Нововведение: #10
Отдельные методы для работы с timeout
Junit 5Junit 5 Junit 4Junit 4
@Test(timeout=1000)
public void testWithTimeout() {
//Code
}
@Test
void testWithTimeout() {
assertTimeout(ofSeconds(5),
() -> TimeUnit.SECONDS.sleep(10));
}
22. Let's Talk About Junit 5
Модель расширений
“Prefer extension points over features”“Prefer extension points over features”
Основной принцип Junit 5
Extension Points
23. Let's Talk About Junit 5
Абстрактный пример
Один интерфейс на каждый extension point
Управление контекстом происходит через аргументы
метода
Использование несколько extension points в реализации
public class OurPoint implements ExtensionPoints {
// @Override method’s which we need to override!
}
24. Let's Talk About Junit 5
Расширения
Test Instance Post Processing
Parameter Resolution
Conditional Test Execution
25. Let's Talk About Junit 5
Применения Extension Points
@ExtendWith(Clazz.class)
Мета-аннотация
26. Let's Talk About Junit 5
Задача
Мы хотим узнать, сколько каждый тест
занимает времени. Как это сделать?
Использовать интерфейсы Extension Point:
BeforeEachCallback, AfterEachCallBack
27. Let's Talk About Junit 5
Реализация
public class PerfomanceBenchmark implements
BeforeEachCallback, AfterEachCallback {
@Override
public void afterEach(TestExtensionContext con) throws
Exception {
//Code
}
@Override
public void beforeEach(TestExtensionContext con) throws
Exception {
//Code
}
28. Let's Talk About Junit 5
Применение через @ExtendWith
@ExtendWith(PerfomanceBenchmark.class)
public class JUnit5Test {
//Тесты
}
29. Let's Talk About Junit 5
Применение через мета аннотацию
@Retention(RetentionPolicy.RUNTIME)
@ExtendWith(PerfomanceBenchmark.class)
public @interface PerfomanceBenchmarks {}
Junit 5 рекурсивно проверяет аннотации у элемента
@Test
@PerfomanceBenchmarks
void ourThirdTest() {
assertTrue(true, "DEVDAY СБТ");
}
30. Требуется записать видео прохождения теста.
А еще хотелось бы знать время затраченное
на каждый тест. Как быть?
Let's Talk About Junit 5
Задача
Использовать интерфейсы Extension Point:
BeforeEachCallback, AfterEachCallBack
31. Let's Talk About Junit 5
Реализация
public class VideoCondition implements BeforeEachCallback,
AfterEachCallback {
@Override
public void beforeEach(TestExtensionContext con) throws Exception {
//Получить значение параметра аннотации, начать видеозапись
}
@Override
public void afterEach(TestExtensionContext con) throws Exception {
//Остановить видеозапись
}
}
32. Let's Talk About Junit 5
Использование
@Retention(RetentionPolicy.RUNTIME)
@ExtendWith(VideoCondition.class)
public @interface Video {}
@VideoAndPerfomanceBenchmarks
void ourTest() {…}
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Video
@PerfomanceBenchmarks
@Test
public @interface VideoAndPerfomanceBenchmarks{}
33. Хочу перезапустить тест, если они упадет по
определенному Exception. Что делать?
Let's Talk About Junit 5
Задача
Использовать интерфейсы Extension Point:
TestTemplateInvocationContextProvider,
AfterTestExecutionCallback
TestTemplateInvocationContext
39. Let's Talk About Junit 5
Top questions
1. Difference between @Before, @BeforeClass, @BeforeEach and @BeforeAll
2. Surefire is not picking up Junit 5 tests
3. Как запускать тесты, когда IDE не поддерживает Junit 5
4. Пропал метод asertThat()
5. Интеграция с Allure 2.0/Allure
40. Let's Talk About Junit 5
Вывод
Использование Java 8;
Много нового функционала;
Один модуль, одна задача;
Гибкое API для построения своего
фреймворка.
Проблемы:
Плагин в Idea не понимает файлы с названием $2_FeaturesTest, FeaturesTest1, а в таких файлов могут быть тесты.
Плагин в Idea на версии Milistone 3.0, выкидывает ошибку, если тестовый метод называется test
Все что я буду говорить и рассказывать основано на моем опыте и на моей точке зрения. За весь код, который будет продемонстрирован сегодня, ответственности не несу)
На данном слайде представлена статистика использование junit на проектах github и мы видим, что Junit занимает лидирующую позицию.
Сергей Пирогов, так же приводил статистику сравнения, у него выйграл TestNG, но это был какой-то зарубежный сайт.
Кто использует этот фреймворк? Поднимите руки. А кто пользуется TestNG? – Вставить в речь!
Рассказываю про roadmap Junit 5;
Про этапы, которые были и будут;
Рассказать, что Marc Philip будет на гейзенбаге и можно послушать его. Будет демонстрировать LiveCoding.
Пользователи собрали денег.
Нужны были крутые вищи
Евро был под 70 руб за одно еуро)
К самой сладки вещи перейти.
Новая архитектура представляет из себя модульность.
Сейчас у нас не большой толстый Jar-ник, который был в предыдущей версии 4, а от отдельные модули отвечающие за свою работу.
Jupiter – с помощью данного модуля пишем тесты.
Vintage – Запуск тестов версии 5, в версии 4 с помощью @RunWith. Легкая миграция тестов от версии 4 к 5 версии.
Platroftm – Служит для запуска и выполнения тестов. Третьи лица, также могут вносить свои реализации тестового движка (через имплементацию junit-platform-engine и регистрацию их движков).
Почему назвали Jupiter: Потому-что пятая планета от солнца.
Почем назвали Vintage: Чтобы обозначить Legacy. Теперь можно к разработчикам ходить и говорить “Что это за винтажный код”.
Слова к данному слайду: JUnit 5 by Marc Philipp - YouTube [720p] (Минута 26:39)
Самая кил фича, которая всех убила – это изминение имен анноатций жизненого цикла теста.
Дальше еще лучше! Теперь чтобы отключить тест мы используем, другую аннотацию.
Кто ответит сколько отличий присутствует между Junit 4 vs Junit 5 тот получит приз?
1) Было:Asserts стало Assertions.assertTrue();
2) Рассказать, что переехали пакеты!
3) Появилась возможность использовать лямбда выражения; Ленивая инициализация сообщения (т.е подгружаем, когда обращаемся). Принимает Supplier
4) Больше не надо модификатора доступа public – бережем наши пальчики от нажатия на клавиши
Правильно,
Изменилось местоположение аннотации @Test
Класс Assert изменен на Assertions и поменялось так же его расположение
Не требуется модификатора доступа public
Изменены расположение параметров в методе AssertTrue
Появилось лямбда выражение
1) Было:Asserts стало Assertions.assertTrue();
2) Рассказать, что переехали пакеты!
3) Появилась возможность использовать лямбда выражения; Ленивая инициализация сообщения (т.е подгружаем, когда обращаемся). Принимает Supplier
4) Больше не надо модификатора доступа public – бережем наши пальчики от нажатия на клавиши
В Junit 4, чтобы реализовать групповые проверки (т.е делаем ассерт и если проверка не прошла то проверяем дальше, то необходимо было использовать правило ErrorCollector).
Теперь в Junit 5, больше нету правил – их убрали. Для того чтобы сделать групповую проверку используем метод assertAll, которые принимает варарг проверок.
Dependency Injection for Constructors and Methods
1) The TestInfo can then be used to retrieve information about the current test such as the test’s display name, the test class, the test method, or associated tags
2) The TestReporter can be used to publish additional data about the current test run. The data can be consumed through TestExecutionListener.reportingEntryPublished() and thus be viewed by IDEs or included in reports.
3) ParameterResolver defines the API for Extensions that wish to dynamically resolve parameters at runtime.If a constructor for a test class or a @Test, @BeforeEach, @AfterEach, @BeforeAll, or @AfterAll method accepts a parameter, the parameter must be resolved at runtime by a ParameterResolver.
Implementations must provide a no-args constructor.
Чтобы запускать параметрезированные тесты в 4-ой версии, нам необходимо было указать наш раннер класс (Parameterized.класс), добавить конструктор и дата провайдер с аннотацией @Parameterized.Parameters, который генерил наши данные для тестов. Минус в том, что мы не смогли комбинировать раннеры в месте.
В 5-ой версии, механизм работы с параметризованными тестами был доработано.
Теперь поддержка параметризованных тестов допускается с помощью аннотаций на методы. Мы должны явно указать что это параметризованный тест и указать конкретный источник по генерации данных. В текущей версии допускается, следующие типы: @ValueSource, @EnumSource, @MethodSource (Два провайдера переберут все значение в каждом провайдере). Дата провайдеры по генерации тестовых данных должны быть static.
Чтобы запускать параметрезированные тесты в 4-ой версии, нам необходимо было указать наш раннер класс (Parameterized.класс), добавить конструктор и дата провайдер с аннотацией @Parameterized.Parameters, который генерил наши данные для тестов. Минус в том, что мы не смогли комбинировать раннеры в месте.
В 5-ой версии, механизм работы с параметризованными тестами был доработано.
Теперь поддержка параметризованных тестов допускается с помощью аннотаций на методы. Мы должны явно указать что это параметризованный тест и указать конкретный источник по генерации данных. В текущей версии допускается, следующие типы: @ValueSource, @EnumSource, @MethodSource (Два провайдера переберут все значение в каждом провайдере). Дата провайдеры по генерации тестовых данных должны быть static.
Conditional Test Execution = ContainerExecutionCondition and TestExecutionCondition
Test Instance Post Processing = Внедрение зависимостей тестовый инстанс, вовлекая различные кастомные методы в тестовый инстанс
Наследуем интерфейсы: TestTemplateInvocationContextProvider и TestTemplateInvocationContextProvider
Но как мы знаем что интерфейс: TestTemplateInvocationContext предоставляем метод getDisplayName () для работы с именем теста, то мы можем модифицировать имена.
От каких болей Junit избавляет.
Рассказать почему Juinit порвет testnG - интерактив
Цель сделать наши тесты понятными с минимальным количеством кода
Ассерты остались такие же, кроме того что изминилась расположение сообщений.
assertThat в Junit 5 больше нет, но если необходимо то можно его подключить из библиотеки org.hamcrest
Добавить еще ссылки
Дамы и господа, спасибо за внимание. Всем желаю успехов в использовании Junit 5. На этом все. Готов услышать ваши вопросы.