Що таке розробка через тестування?

Використовуйте методологію TDD і наданий набір тестів, щоб розвʼязувати вправи


Розробка через тестування (іноді її називають розробкою від тестів або проєктуванням через тестування) - це практика, за якої ми спершу пишемо модульні тести, а вже потім беремося за код реалізації. Жодного рядка коду реалізації до тестів.

На Exercism тести і є вимогами!

Усі практичні вправи, над якими ми працюємо (ті, що не вчать нового поняття), мають інструкції, які в загальних рисах описують, що потрібно зробити. Так задумано: ці інструкції не враховують подробиць реалізації, притаманних конкретній мові програмування, бо ними користуються всі 70+ мовних треків Exercism. Деякі мовні треки додають до них докладніші подробиці, але не всі.

Коли ми беремося за практичну вправу, варто уважно прочитати інструкції. Вони дадуть загальне уявлення про те, як підступитися до реалізації рішення. Але щоб зрозуміти повні й точні вимоги, доведеться прочитати тести:

  • Чи має результат бути структурою даних певного типу?
  • Чи має результат бути відсортований у певному порядку?
  • Як саме слід обробляти винятки? І так далі.

Вправу розвʼязано тоді, коли всі надані тести запускаються й проходять. Інакше кажучи, наше рішення не просто тлумачить інструкції так, щоб «мало правильний вигляд», а є програмою, яка відповідає наданим тестам. Тести і є повними вимогами до вправи.

Як Exercism застосовує TDD?

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

Памʼятаймо: підхід TDD допоможе дійти до рішення, але на цьому не обовʼязково зупинятися. Якщо є бажання розширити рішення за межі вимог, це цілком доречно. Якщо ми вирішимо попрацювати з наставником (а ми радимо це зробити, щойно тести почнуть проходити), він допоможе відрефакторити й удосконалити початкову реалізацію або навіть запропонує нові модульні тести.

Робота в онлайн-редакторі

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

Коли не проходять кілька тестів, сайт спершу показує результат лише першої невдачі. Можна натиснути на інші невдачі, щоб розгорнути й їх! Іноді перший результат може виявитися не найінформативнішим.

Не варто засмучуватися через велику кількість тестів, що не проходять. Зосередьмося на тому, щоб вони проходили один за одним.

Робота локально

Багато треків використовують «пропущені» тести у своїх файлах тестів. Спочатку «активний» лише перший тест, а решта неактивні (як саме це відбувається, залежить від треку). Коли ми запускаємо набір тестів у своєму середовищі, виконується лише перший тест. Ми робимо це, щоб заохотити дотримуватися такого робочого процесу:

  1. Перш ніж додавати новий код, запускаємо набір тестів: маємо побачити тест, що не проходить.
  2. Додаємо рівно стільки коду, скільки потрібно, щоб тест пройшов.
  3. Запускаємо набір тестів.
  4. Якщо тест усе ще не проходить, повторюємо крок 2.
  5. Коли тест пройшов, рефакторимо код на власний розсуд, стежачи, щоб усі активні тести й далі проходили. Рефакторинг може охоплювати:
    • вилучення дубльованого коду,
    • розбиття довгих функцій на менші,
    • додавання коментарів тощо.
  6. Знімаємо позначку пропуску з наступного тесту й повторюємо з кроку 1.

Повторюємо ці кроки, доки не знімемо позначки пропуску з усіх тестів. Коли всі тести проходять, вітаємо, вправу розвʼязано!

Те, як саме з тестів знімають позначку пропуску (або як їх активують), залежить від треку. У деяких треках це може бути закоментування або вилучення анотації. В інших - зміна атрибута з true на false. Варто приділити час і прочитати документацію для свого треку; там ці подробиці пояснено.

У треках, де тести не пропускають, цей процес може бути таким простим, як закоментувати всі тести й розкоментувати їх по одному.

Навіщо потрібна розробка через тестування

Хоч це й може здатися «ставленням воза поперед коня», є кілька вагомих причин писати модульні тести раніше за код реалізації.

  1. Проєктування. Це змушує спершу подумати про інтерфейс програми (про те, як вона відкриває свою функціональність світові), а не кидатися одразу до того, як реалізувати код. Добре спроєктований (і придатний до тестування!) інтерфейс часто важливіший за ефективну реалізацію.

  2. Дисципліна. Написання тестів часто сприймають як обтяжливий обовʼязок або щось другорядне; якщо писати тести першими, то врешті-решт буде написано достатньо модульних тестів, щоб покрити більшість функціональності коду чи навіть усю (замість того, щоб так і не дійти до цього).

  3. Менше роботи. Якщо дотримуватися щільного циклу, у якому ми пишемо один тест, потім код, що його реалізує, а потім наступний тест, код зростає органічно. Часто (хоч і не завжди) це означає менше марно витрачених зусиль: у результаті буде написано весь потрібний код і жодного зайвого.

Додаткові матеріали