Модуль 8 · урок 8 з 9
Що не тестувати
Коротший урок за всі попередні, але, можливо, найкорисніший. Поганий тест гірший за його відсутність: він займає час на написання, ламається при кожному рефакторингу й нічого не ловить.
Що не тестувати
| Що | Чому ні |
|---|---|
| Геттери й сеттери | Перевіряють мову, а не твій код |
| Чужі бібліотеки | Що debounceTime чекає — уже перевірено авторами RxJS |
| Сам Angular | Що inject() віддає сервіс — не твоя відповідальність |
| Верстку й стилі | Відступи й кольори змінюються постійно |
| Точні тексти інтерфейсу | Копірайтер перепише — тест упаде без причини |
| Приватні методи | Тестуй через публічний інтерфейс; інакше рефакторинг неможливий |
| Тривіальні мапери | Якщо це просто перейменування полів — цінності нуль |
Ознаки поганого тесту
// ❌ повторює реалізацію рядок у рядок
it('фільтрує', () => {
const result = applyState(rows, state);
expect(result.items).toEqual(rows.filter(r => r.status === state.status));
});
Такий тест не перевіряє поведінку — він переписує її вдруге. Якщо в реалізації помилка, у тесті буде та сама помилка, і він пройде. Правильно — очікуваний результат пишеться руками: конкретні три обʼєкти, які мають лишитись.
// ❌ залежить від порядку виконання
let store: TaskStore;
beforeAll(() => { store = new TaskStore(api); }); // стан тече між тестами
// ✅ свіжий стан на кожен тест
beforeEach(() => { store = new TaskStore(api); });
// ❌ перевіряє все одразу — при падінні незрозуміло що саме
it('працює', () => {
expect(result.items.length).toBe(3);
expect(result.total).toBe(10);
expect(store.loading).toBe(false);
expect(api.list).toHaveBeenCalled();
// … ще десять перевірок
});
Один тест — одна поведінка. Не буквально одне expect: перевірок може бути
кілька, якщо вони описують одну річ. Але «працює» з пʼятнадцятьма перевірками —
це не тест, а сигналізація без адреси.
Про покриття
ng test --code-coverage
# Statements : 78% · Branches : 65% · Functions : 82%
Покриття корисне як карта непокритого: подивитись, які файли взагалі не мають тестів, і чи немає серед них чогось важливого. Але як мета воно шкідливе: сто відсотків легко набиваються тестами, які викликають код і нічого не перевіряють.
Для навчального проєкту цифра взагалі не потрібна. Потрібні пʼять тестів, які перевіряють те, де є справжня логіка: фільтрація й сортування, стан стору, валідатори, guard. Якщо лід спитає про покриття — відповідь із уроку 1 цього модуля: «не ганявся за цифрою, покрив те, де є логіка».
Коли тест таки варто написати
- Знайшовся баг. Спершу тест, який його відтворює, потім виправлення. Так він не повернеться.
- Логіка з гілками. Кожна умова — це шанс помилитись.
- Обчислення. Дати, гроші, відсотки, сортування — усе, де легко переплутати знак.
- Інваріант, від якого залежить інше. Наприклад, що незмінені елементи зберігають
посилання — від цього залежить
OnPush. - Складний рефакторинг попереду. Тести дають змогу переписати впевнено.