Библиотеки assert’ов
В core, admin и других сервисах
Илья Изиланов 09.08.2023
Доклад
22
Для чего мы
вообще
пишем
тесты?
3
Хороший тест
@Test
void good_test() {
}
44
Ещё лучше
@Test
void better_test() {
[Link]();
}
55
Для чего мы Чтобы они падали
вообще
пишем
тесты?
6
Напишем падающий тест
@Test
void list_contains() {
List<String> list = [Link]("elem1", "elem2", "elem3");
String existingElem = "elem1";
String nonExistingElem = "elem4";
assertTrue([Link](existingElem));
assertTrue([Link](nonExistingElem));
}
77
Напишем падающий тест
[Link]:
Expected :true
Actual :false
<Click to see difference>
at
[Link].T01_AssertContainsTest.list_contains(T01_AssertConta
[Link])
at [Link]/[Link]([Link])
at [Link]/[Link]([Link])
at [Link]/[Link]([Link])
88
Улучшим падающий тест
@Test
void list_contains() {
List<String> list = [Link]("elem1", "elem2", "elem3");
String existingElem = "elem1";
String nonExistingElem = "elem4";
assertTrue([Link](existingElem), "expected elem1 to be in the
list");
assertTrue([Link](nonExistingElem), "expected elem4 to be in the
list");
}
99
Улучшим падающий тест
[Link]: expected elem4 to be in the list ::>
Expected :true
Actual :false
<Click to see difference>
at
[Link].T01_AssertContainsTest.list_contains(T01_AssertConta
[Link])
at [Link]/[Link]([Link])
at [Link]/[Link]([Link])
at [Link]/[Link]([Link])
10
10
Добавим вывод списка
@Test
void list_contains() {
List<String> list = [Link]("elem1", "elem2", "elem3");
String existingElem = "elem1";
String nonExistingElem = "elem4";
assertTrue([Link](existingElem), "expected elem1 to be in the
list " + list);
assertTrue([Link](nonExistingElem), "expected elem4 to be in the
list " + list);
}
11
11
Добавим вывод списка
[Link]: expected elem4 to be in the list
[elem1, elem2, elem3] ::>
Expected :true
Actual :false
<Click to see difference>
at
[Link].T01_AssertContainsTest.list_contains(T01_AssertConta
[Link])
at [Link]/[Link]([Link])
at [Link]/[Link]([Link])
at [Link]/[Link]([Link])
12
12
Конкатенации
@Test
void list_contains() {
List<String> list = [Link]("elem1", "elem2", "elem3");
String existingElem = "elem1";
String nonExistingElem = "elem4";
assertTrue([Link](existingElem), "expected elem1 to be in the
list " + list);
assertTrue([Link](nonExistingElem), "expected elem4 to be in the
list " + list);
}
13
13
Лямбды!
@Test
void list_contains() {
List<String> list = [Link]("elem1", "elem2", "elem3");
String existingElem = "elem1";
String nonExistingElem = "elem4";
assertTrue([Link](existingElem), () :> "expected elem1 to be in
the list " + list);
assertTrue([Link](nonExistingElem), () :> "expected elem4 to be
in the list " + list);
}
14
14
Лямбды!
[Link]: expected elem4 to be in the list
[elem1, elem2, elem3] ::>
Expected :true
Actual :false
<Click to see difference>
at
[Link].T01_AssertContainsTest.list_contains(T01_AssertConta
[Link])
at [Link]/[Link]([Link])
at [Link]/[Link]([Link])
at [Link]/[Link]([Link])
15
15
Для чего мы Чтобы они падали
Поэтому нам важны сообщения об
вообще ошибках
пишем
тесты?
16
Мы все сделали сами
[Link]: expected elem4 to be in the list
[elem1, elem2, elem3] ::>
Expected :true
Actual :false
<Click to see difference>
at
[Link].T01_AssertContainsTest.list_contains(T01_AssertConta
[Link])
at [Link]/[Link]([Link])
at [Link]/[Link]([Link])
at [Link]/[Link]([Link])
17
17
Assertj to the rescue!
@Test
void list_contains() {
List<String> list = [Link]("elem1", "elem2", "elem3");
String existingElem = "elem1";
String nonExistingElem = "elem4";
assertThat(list)
.contains(existingElem)
.contains(nonExistingElem);
}
18
18
Assertj to the rescue!
[Link]:
Expecting ListN:
["elem1", "elem2", "elem3"]
to contain:
["elem4"]
but could not find the following element(s):
["elem4"]
at
[Link].T01_AssertContainsTest.assertj_test(T01_AssertContai
[Link])
at [Link]/[Link]([Link])
at [Link]/[Link]([Link])
at [Link]/[Link]([Link])
19
19
Вы всё подстроили!
Это работает только в
простых кейсах!
Реальные примеры
Казалось бы…
@Test
public void dateFormatting() {
LocalDate firstQuarterStart = [Link]("2020-01-01");
LocalDate secondQuarterStart = [Link]("2020-04-01");
LocalDate thirdQuarterStart = [Link]("2020-07-01");
LocalDate fourthQuarterStart = [Link]("2019-10-01");
assertEquals([Link](firstDateTest),
firstQuarterStart);
assertEquals([Link](secondDateTest),
secondQuarterStart);
assertEquals([Link](thirdDateTest),
thirdQuarterStart);
assertEquals([Link](fourthDateTest),
fourthQuarterStart); 22
22
Expected: null
[Link]:
Expected :null
Actual :2020-01-01
<Click to see difference>
at
[Link].T03_DateFormattingTest.dateFormatting(T03_DateFormat
[Link])
at [Link]/[Link]([Link])
at [Link]/[Link]([Link])
at [Link]/[Link]([Link])
23
23
Как так? 24
Для чего мы Чтобы они падали
Поэтому нам важны сообщения об
вообще ошибках
пишем Документация
тесты?
25
Тинейджеры
@Test
void teenagersFiltering() {
List<ClientOfferDetailsDto> teenagerResponse =
[Link](
[Link](), [Link]([Link](), [Link](),
[Link]()))
.getData();
Set<Long> teenagerOfferIds =
[Link]().map(ClientOfferDetailsDto::getId).collect(Collect
[Link]());
step("Проверить: в ответе метода присутствуют офферы 1 и 3 из
предусловия", () :> {
assertAll(
() :> assertEquals(2, [Link](), "teenagerResult
should has 2 offers"),
() :> assertTrue([Link]([Link]()), 26
26
Для чего мы Чтобы они падали
Поэтому нам важны сообщения об
вообще ошибках
пишем Документация
Поэтому нам важна простота и
тесты? семантика кода
27
Тинейджеры
@Test
void teenagersFiltering() {
List<ClientOfferDetailsDto> teenagerResponse =
[Link](
[Link](), [Link]([Link](), [Link](),
[Link]()))
.getData();
step("Проверить: в ответе метода присутствуют офферы 1 и 3 из
предусловия", () :> {
:/ then
assertThat(teenagerResponse)
.map(ClientOfferDetailsDto::getId)
.as("teenagerResponse contains offer1 id and offer3 id")
.containsExactlyInAnyOrder([Link](), [Link]());
});
} 28
28
Примеры из wallet
assertThat([Link]())
.usingComparatorForType(ObjectUtils::compare, [Link])
.usingRecursiveFieldByFieldElementComparator()
.containsExactlyInAnyOrderElementsOf(expectedCardsmobileOffers)
public static void assertEqualDates(LocalDateTime expected, LocalDateTime
actual, String message) {
assertThat(expected)
.withFailMessage(message)
.isCloseTo(actual, within(1, [Link]));
}
29
29
Пример из admin
private void assertMerchantSubjectRequisiteDto(MerchantSubjectRequisiteDto
expect, MerchantSubjectRequisiteDto actual) {
assertEquals([Link](), [Link](), "Bank should be
equals");
assertEquals([Link](), [Link](), "Bic should be equals");
assertEquals([Link](), [Link](), "Email should be
equals");
assertEquals([Link](), [Link](),
"FactAddress should be equals");
assertEquals([Link](), [Link](), "Inn should be equals");
assertEquals([Link](), [Link](), "Kpp should be equals");
assertEquals([Link](), [Link](), "Ks should be equals");
assertEquals([Link](), [Link](), "LoanDate
should be equals");
assertEquals([Link](), [Link](),
"LoanNumber should be equals");
assertEquals([Link](), [Link](), "Ogrn should be 30
30
Пример из admin
private void assertMerchantSubjectRequisiteDto(MerchantSubjectRequisiteDto
expect, MerchantSubjectRequisiteDto actual) {
assertThat(actual)
.usingRecursiveComparison()
.ignoringFields("mSubjectID")
.isEqualTo(expect);
}
31
31
Это все хорошо, но у нас куча
кода
Способы миграции:
• Boy scout rule
• Скрипты
32
Recap
Разработчики Бизнес
Улучшается DX: Уменьшается TTM:
• Код чище • Старые баги
• Кода меньше • Новые фичи
• Легче дебагать
33