Forward from: ✙rozho)))k✙🇺🇦
100% coverage тести, які нічого не тестують
В далекому 2010 році, коли долар був по 8, я працював на ентерпрайзному проєкті разом з консультантами з компанії Thoughtworks. Тієї, звідки Мартін Фаулер, тієї, що публікує Technology Radar, за яким, ви, ймовірно стежите.
На нашому проєкті не було тестів, тому що в компанії на той час не було культури тестування. Власне, мінусів у такому підході я не бачу, але то вже інша історія.
Консультанти звісно відразу ж прийнялись виправдовувати свій рейт у 3000$ за день роботи та заявили що для успіху проєкту неодмінно потрібно мати високе покриття тестами.
Наш код у 90% випадків виглядав приблизно так:
class Action {
public void doThing(Context context) {
ResultOne resultOne = ServiceOne.getInstance().doThing(context);
ResultTwo resultTwo = ServiceTwo.getInstance().doThing(context, resultOne);
context.setResult(resultTwo);
}
}
Типова імперативно-процідурна ентерпрайзна локшина, де всі та все ходять у бази та зовнішні інтеграції.
Звісно, з коробки такий код не є тестабельним, через статичні методи. Тому спочатку консультанти винесли сервіслукап в окремі методи, а згодом ми зробили там вже нормальний DI.
Але, оскільки більшість коду ходила кудись назовні, то потрібно було писати моки та стаби (різницю питають у вас на співбесідах), а самі тести зводилися до того що ми перевіряли що мок викликається з необхідним параметром, та виглядали десь отак:
class ActionTest {
@Test
public void testDoThing() {
ServiceOne mockServiceOne = mock(ServiceOne.class);
ServiceTwo mockServiceTwo = mock(ServiceTwo.class);
Action action = new Action(mockServiceOne, mockServiceTwo);
Context context = mock(Context.class);
ResultOne mockResultOne = mock(ResultOne.class);
ResultTwo mockResultTwo = mock(ResultTwo.class);
when(mockServiceOne).doThing(eq(context)).thenReturn(mockResultOne);
when(mockServiceTwo).doThing(eq(context), eq(mockResultOne)).thenReturn(mockResultTwo);
action.doThing(context);
verify(mockServiceOne).doThing(context);
verify(mockResultTwo).doThing(context, mockResultTwo);
verify(context).setResult(mockResultTwo);
}
}
Таких тестів ми писали сотні. Цілі спринти були присвячені ретельному моканню. Каверадж відразу полетів у небеса.
Але, як ми можете здогадатися, ці тести нічого не тестували, а просто викривленим чином дублювали вже написану програму, та радикально ускладнювали рефакторинг.
Згодом, я зустрічав такі «тести» в інших компаніях на інших проєктах.
Формально каверадж є, а по факту ні.
Писали такі тести? Згодні з тим що вони марні чи вважаєте що все правильно нам консультанти сказали? Діліться у коментах👇
#робота
permalink | @full_of_hatred
👇Щоденні донати💰на ЗСУ🪖
🫡@Donate1024Bot
В далекому 2010 році, коли долар був по 8, я працював на ентерпрайзному проєкті разом з консультантами з компанії Thoughtworks. Тієї, звідки Мартін Фаулер, тієї, що публікує Technology Radar, за яким, ви, ймовірно стежите.
На нашому проєкті не було тестів, тому що в компанії на той час не було культури тестування. Власне, мінусів у такому підході я не бачу, але то вже інша історія.
Консультанти звісно відразу ж прийнялись виправдовувати свій рейт у 3000$ за день роботи та заявили що для успіху проєкту неодмінно потрібно мати високе покриття тестами.
Наш код у 90% випадків виглядав приблизно так:
class Action {
public void doThing(Context context) {
ResultOne resultOne = ServiceOne.getInstance().doThing(context);
ResultTwo resultTwo = ServiceTwo.getInstance().doThing(context, resultOne);
context.setResult(resultTwo);
}
}
Типова імперативно-процідурна ентерпрайзна локшина, де всі та все ходять у бази та зовнішні інтеграції.
Звісно, з коробки такий код не є тестабельним, через статичні методи. Тому спочатку консультанти винесли сервіслукап в окремі методи, а згодом ми зробили там вже нормальний DI.
Але, оскільки більшість коду ходила кудись назовні, то потрібно було писати моки та стаби (різницю питають у вас на співбесідах), а самі тести зводилися до того що ми перевіряли що мок викликається з необхідним параметром, та виглядали десь отак:
class ActionTest {
@Test
public void testDoThing() {
ServiceOne mockServiceOne = mock(ServiceOne.class);
ServiceTwo mockServiceTwo = mock(ServiceTwo.class);
Action action = new Action(mockServiceOne, mockServiceTwo);
Context context = mock(Context.class);
ResultOne mockResultOne = mock(ResultOne.class);
ResultTwo mockResultTwo = mock(ResultTwo.class);
when(mockServiceOne).doThing(eq(context)).thenReturn(mockResultOne);
when(mockServiceTwo).doThing(eq(context), eq(mockResultOne)).thenReturn(mockResultTwo);
action.doThing(context);
verify(mockServiceOne).doThing(context);
verify(mockResultTwo).doThing(context, mockResultTwo);
verify(context).setResult(mockResultTwo);
}
}
Таких тестів ми писали сотні. Цілі спринти були присвячені ретельному моканню. Каверадж відразу полетів у небеса.
Але, як ми можете здогадатися, ці тести нічого не тестували, а просто викривленим чином дублювали вже написану програму, та радикально ускладнювали рефакторинг.
Згодом, я зустрічав такі «тести» в інших компаніях на інших проєктах.
Формально каверадж є, а по факту ні.
Писали такі тести? Згодні з тим що вони марні чи вважаєте що все правильно нам консультанти сказали? Діліться у коментах👇
#робота
permalink | @full_of_hatred
👇Щоденні донати💰на ЗСУ🪖
🫡@Donate1024Bot