Щоб перевірити систему, виділіть побічні ефекти

Виведення побічних ефектів - один з найкращих способів побудови тестового коду

Зображення бокс-матчу між двома бійцями-чоловіками. Їх обличчя поза рамкою. Боєць ліворуч відправив лівий гачок бійцю в правій. Боєць праворуч у червоному шорті з маленьким символом Радянського Союзу.

Nock - відома бібліотека, написана на JavaScript, корисна для заглушення мережевих запитів. Він повертає статичну відповідь для тестів, щоб вони могли працювати, навіть якщо HTTP-сервер недоступний.

Однак це також запах.

Отримане з'єднання між Джерелом даних та Тестовою системою - це вартість, яка може вплинути на рефакторинг коду та ремонтопридатність.

Ось чому.

Скажімо, є сервер, який повертає список публікацій і функція, яка вимагає відповіді з цього сервера для створення списку заголовків публікацій. Тест функції використовує Nock для заглушення відповіді від сервера:

Діаграма, яка показує блок зліва з підписом

Код має пристойне покриття. Однак з цим є деякі проблеми.

Якщо ви внесете зміни до типу вмісту відповіді, вам доведеться змінити тести, навіть якщо поведінка коду залишається такою ж:

Це ж стосується, якщо ви внесете зміни в URL, заголовки або параметри, які Nock заглушує. Ви повинні змінити тести, навіть якщо поведінка системи залишається такою ж:

Функція "створення списку дописів" - це система під тестом (SUT). Дані з HTTP-дзвінка є Джерелом даних.

Ви можете сконструювати код так, щоб джерело даних мав загальний інтерфейс, який підключається до SUT. У такому випадку ви можете користуватися логікою без необхідності занадто великої настройки.

Діаграма, що показує блок зліва із заголовком

Для тестового середовища можна ввести "Джерело даних в пам'яті". Для виробництва можна використовувати "Джерело даних HTTP-сервера".

"Загальний інтерфейс" у попередньому JSFiddle - це метод "знайти заголовок повідомлень". Незалежно від того, як ви будуєте інтерфейс, ви маєте контроль над усіма абонентами. Тому зміни прямолінійні. Мартін Фаулер називає це "неопублікованим інтерфейсом".

З іншого боку, якщо сервер розриває контракт свого Опублікованого інтерфейсу, скажімо, атрибут класу змінюється від пост-заголовка до заголовка статті, потрібно лише змінити реалізацію джерела даних. Вам не доведеться вносити зміни скрізь.

Тест, який важливо перевірити та мати ранній відгук, - це тести на поведінку, а не дані. Тому важливо розробити код, щоб зменшити кількість зусиль, необхідних для зміни логіки. У цьому випадку логіка - це перетворення вхідних даних із Джерела даних у список не упорядкованих HTML.

З новим дизайном ви роз'єднали Джерело даних із тестованої системи. Тому ви можете видалити Нок.

Новий дизайн також зменшує роботу, необхідну для додавання нового правила до системи без копіювання / вставки:

І все-таки "Джерело даних HTTP-сервера" має деяку неперевірену логіку всередині приватної функції "запит заголовка повідомлень з html".

Щоб перевірити це, ви можете повторити ту саму схему. Натисніть на побічні ефекти та перетворіть механізм «отримати запит» у підключення до «Джерела даних HTTP-сервера». Таким чином, ви все ще можете протестувати код, не потребуючи Нока:

Оскільки у вас вже є тести на підтвердження роботи "списку публікацій публікацій" із "Джерелом даних в пам'яті", ви можете вирішити перевірити Джерело даних ізольовано, щоб переконатися, що він повертає правильний результат:

Ви повністю виштовхнули побічний ефект із логіки. У цьому випадку реальна функція "отримати запит" є побічним ефектом. Тепер ви можете використовувати Nock, щоб прикрити це.

Однак, враховуючи, що логіка всередині "отримати запит" є тривіальною, і Нок має значну вартість, має сенс мати невелику кількість інтеграційних тестів, які можуть реалізувати всю програму, включаючи побічний ефект. Ви можете використовувати Nock, щоб уникнути підключення до живого сервера, і все ж використовуйте HTTP-запити, щоб перевірити, чи додаток повертає розумну відповідь, коли всі шматки поєднуються разом.

Nock корисно закріпити з'єднання в рівні HTTP та надати статичну відповідь. Однак користуйтеся нею помірно. З кожним тестом, який ви заглушите, ви збільшуєте значну прив'язку та вартість змін.

Якщо не використовувати його економно, Nock може створити пекло Nock.

Проблема, яку ви хочете вирішити, - зменшити кількість помилок та вартість змін. Якщо змінити структуру коду без змін поведінки, тести не повинні порушуватися. Якщо вони це роблять, то ви не змогли написати корисних тестів.

Ваша мета повинна полягати в тому, щоб поліпшити якість тестового покриття до логіки, яка вам важлива, і досягти раннього зворотного зв'язку. Все це, не впливаючи на вашу здатність перефактурувати код.

Виділіть побічні ефекти та обмежте використання таких інструментів, як Nock, межами програми.

Це повинно дати вам достатньо впевненості, щоб внести зміни, а не порушувати речі.

Вступайте в бій, висувайте побічні ефекти, а потім… Відступайте.

Дякуємо за прочитане Якщо у вас є відгуки, зв’яжіться зі мною у Twitter, Facebook або Github.

Дякуємо Едуардо Сломпо та Гільгерме Дж. Трамонтіна за їх проникливий відгук на цю посаду.