TDD все ще порівнюють з TLD — думки експертів



Фахівці з декількох Вузів Європи – Давіде Фуччі, Джузеппе Сканиелло, Сімоне Романі, Мартін Шеппэрд, Бойсе Сигвени, Фернандо Уйагуари, Бурак Туран, Наталія Юристо і Марку Ойиво – провели чергове дослідження на тему ефективності тестування. Вони розглянули методології Test Driven Development (TDD) і Test Last Development (TLD).



Дослідники порівнювали їх за двома показниками – сумарна швидкість розробки продукту і якість вихідного коду. Перша методологія (розробка через тестування – TDD) знову не виправдала покладених надій: популярна раніше схема тестування після розробки (TLD) виявилася менш ефективною. Так що за вказаними вище показниками суттєвих відмінностей вони не виявили.

В такому разі чим же пояснюється спалах інтересу до TDD, коли вона тільки з'явилася? Ця методологія виникла в 2000-х, так що тепер елемент новизни можна сміливо скинути з рахунків. Тим не менш, предметом суперечок вона залишається до цих пір.

Автор TDD Кент Бек виділяє п'ять основних етапів при використанні методології на практиці:

• Написати новий тест-кейс;
• Переконатися, що запуск нового тесту призведе до збою;
• Написати новий або модифікувати код так, щоб тест пройшов успішно;
• Перезавантажити всі інші тести і підтвердити успішне їх проходження;
• Зробити рефакторинг коду, усунувши надмірність.

TDD і TLD мають свої переваги та недоліки. Причому, перевага однієї методології часто є недоліком для іншого.

• Швидкість розробки тестів

У випадку з TDD інженерам доводиться витрачати на 16% більше часу, ніж з TLD. Це пояснюється додатковими витратами на перемикання розробників між написанням тестів і основного коду.

• Поріг входження

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

• Продуктивність і супровід

Завдяки TDD знижуються витрати на супровід програмного продукту. Зазвичай при використанні цієї методології кількість тест-кейсів приблизно на 50% більше, ніж у випадку з TLD. Це дає більше покриття і передбачає підвищену надійність продукту. Тому й супроводжувати таке легше. За рахунок добре продуманої архітектури продуктивність системи, розробленої з використанням, TDD зазвичай вище.

• Обсяг коду

Застосування НАЙВИЩОГО дозволяє істотно скоротити обсяг коду в порівнянні з TDD. Крім того, код з TLD часто має більш просту структуру.

• Внесення змін

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

У будь-якому випадку кожен проект індивідуальний, але загальні закономірності існують — так само, як і існують різні компроміси.

Компроміси
Іван Хватів:
І те, й інше – крайнощі. Все залежить від ситуації. В цілому, тести – це дуже болюча і холиварная тема. Питання ще не закрите про те, які тести взагалі писати треба чи не треба: юніт, функціональні, або інтеграційні (або всі).
Наведемо приклад можливого діалогу між менеджером і архітектором.
А: — Хочемо ми 100% покриттів?
М: — Так, звичайно.
А: — Відмінно, тільки це затягне розробку вдвічі і ускладнить сопровождаемость тестового коду на порядок.
Широко поширена думка про те, що дизайн середньої якості забезпечить покриття ключових шматків коду на 80-85%, а кожні наступні 5% будуть віднімати все більше і більше ресурсів (праці і часу).

Більш того, автор TDD Кент Бек якось висловлював думка, що непотрібні тести можна видаляти. Такі тести він називає delta coverage – додаткове покриття, що забезпечується конкретним набором тестів. Якщо це додаткове покриття дорівнює 0, то тест можна сміливо видаляти.

Кент Бек — розробник програмного забезпечення, творець таких методологій розробки ПЗ як екстремальне програмування (XP) і розробка через тестування (TDD). Бек був одним з 17 фахівців, подписавшихAgile Manifesto в 2001 році.

Зайві тести призводять до додаткових витрат на супровід. Саме тому, тести, отримані на ранніх етапах зазвичай є занадто наївними та можуть бути видалені. Особливо це стосується методології TDD.

Мартін Фаулер навів два простих емпіричних правил, які визначають нижню і верхню межі покриття: якщо ви не впевнені у своїх змінах, і багато з них призводять до збоїв, але не ламають тести, значить тестів занадто мало. Якщо ж при кожній зміні ламається дуже багато тестів, то, можливо, тестів занадто багато.

Мартін Фаулер — автор ряду книг і статей по архітектурі, об'єктно-орієнтованого аналізу і розробки, мови UML, рефакторінгу, екстремального програмування, предметно-орієнтованих мов програмування.

Коли варто використовувати TDD?


На графіку зображена швидкість розвитку двох проектів. Сині принесли в жертву дизайн і тести. Їх мета – якомога швидше реалізувати максимальний обсяг функціональності. Червоні, навпаки, приділяють велику увагу дизайну системи та її тестування.

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

Але за рахунок чого червоні примудряються тримати систему гнучкою і рухатися зі швидкістю? Одна з причин — це використання TDD, пише Олександр Бындю, експерт з Agile і Lean.

Він наводить ряд переваг TDD в проекті червоних:

1. Найпростіше – в такому проекті більше тестів, у порівнянні з звичайним підходом. З одного боку, саме по собі кількість тестів не гарантує більш високої якості проекту і відсутність помилок. З іншого, все залежить від того, наскільки добре ви вмієте писати ці тести. Багато хороших тестів зекономлять багато часу.

2. Код стає більш якісним. Це пов'язано з тим, що модульне тестування передбачає слабку зв'язаність різних модулів системи, інакше буде дуже складно написати ці модульні тести. Тому доводиться застосовувати, наприклад, принципи проектування класів S. O. L. I. D:
Принцип єдиності відповідальності (The Single Responsibility Principle)
Принцип відкритості/закритості (The Open Closed Principle)
Принцип заміщення Лисков (The Liskov Substitution Principle)
Принцип поділу інтерфейсу (The Interface Segregation Principle)
Принцип інверсії залежності (The Dependency Inversion Principle)
В кінцевому рахунку, це дасть всій системі велику мобільність і гнучкість.

3. Ми можемо розбудовувати наш проект скільки завгодно, адаптувати його до нових вимог і не боятися, що після чергового рефакторінгу ми втратимо якусь вже працюючу функціональність. Чому ми можемо собі це дозволити? Тому що після рефакторінгу запустимо всі тести, і вони нам покажуть (зеленою смужкою), що всі бізнес-функції і досі працюють.

Тому, на думку Бындю, TDD змушує писати більш якісний код, який зручніше тестувати. А це означає, що ми залишаємо в коді менше технічних боргів.
Коли ж TDD починає обганяти? Тоді, коли синя і червона лінія перетинаються. В цей час команда синіх щосили починає платити за борги. Звідси висновок про межі застосовності TDD:
Ви можете писати код без TDD, якщо впевнені, що до пунктирної лінії справа не дійде. Наприклад, ви пишете невеликий проект для автоматизації внутрішньої роботи, або створюєте сайт-візитку.
Треба розуміти, що TDD – не гарантія якості вашого коду, але з ним простіше тримати систему в тонусі, підсумовує він.

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

Давид Хейнемейер Ханссон — данська програміст, автор веб-фреймворку Ruby on Rails, засновник Instiki wiki і автогонщик, переможець у класі LMGTE Am (2014) та срібний призер LMP2 (2013) чемпіонату світу з перегонів на витривалість, переможець 24 годин Ле-Мана 2014 року в класі LMGTE Am.

Однак у Мартіна Фаулера є важливе застереження на цей рахунок:
Коли система починає розростатися, то проблема не в кількості рівнів абстракції, а в кількості рівнів ізоляції. Тобто, сам факт того, що клас А викликає метод класу Б, який звертається до класу В не представляє проблему до тих пір, поки між кожним з цих класів не з'являється рівень ізоляції у вигляді інтерфейсу.
З іншого боку на цю тему дивляться деякі користувачі «Хабра».

Думка користувача Volch:
Потрібно розуміти, що застосування таких методологій як TDD припускає, що автотесты пишуть розробники, а не тестувальники. Це методології програмування та кодування, а не розробки готового продукту, в яку залучено безліч людей від ПМов і техписателей до адмінів і техпідтримки. Розробники ж часто ставляться до впровадження TDD-like як взваливанию на них обов'язків тестувальників.
Думка користувача Tagakov:
TDD дійсно не те, що повинні робити тестувальники. Їх завдання писати функціональні тести і, якщо вистачає кваліфікації, інтеграційні. TDD не TDD, але розробники споконвіку займалися тестуванням, запускаючи свій код і перевіряючи як він працює, юніт-тестування це швидше формалізація цього процесу.
Думка користувача Kunis:
Якщо тест написаний до і надано програмісту в якості вихідних даних, він стає «технічною вимогою» (requirement). Зрозуміло, той, хто пише тест, повинен заздалегідь написати і запрограмувати всі необхідні моки. Ха-ха, не хотів би я бути тим програмістом, в обов'язки якого входить програмувати тести для інших.

Ну, а може сам програміст написати тести до свого коду заздалегідь? З мого досвіду, немає і немає. Програмісти (і я і переважна більшість, з ким я обговорював це) просто думають у зворотному напрямку. Так, спочатку люди намагалися чесно слідувати методології. Але через якийсь час починали спочатку писати код, а потім на нього дописувати тести. А ще через якийсь час, тести втратили свою різносторонність і скрупульозність. А потім і зовсім писалися «шоб було», раз вже просять.

А воно взагалі треба?
Адаптація TDD
Свою думку також висловлював один з апологетів розробки через тестування Олександр Люлін:
Я не використовую TDD в його класичному розумінні. Взагалі, навряд чи хтось із професіоналів розглядає енциклопедичні статті в якості керівництва до дії. Ми свій підхід «вистраждали» в рамках реалізації успішного проекту, тому за нами реальний досвід, а не «тупе використання чужих ідей».

Швидше, ми використовуємо синтез з TDD і власних уявлень про те, як потрібно розробляти. Навіть якщо ці «зовнішні ідеї» виходять від дуже розумних людей, їх слід критично осмислити і адаптувати до реальної компанії, існуючої команди і стратегії розвитку і забезпечення якості.
Олег Балбеков, СЕО Vexor:
На наш погляд жорстко розділяти дані підходи досить складно і взагалі не потрібно. Так повелося, що в нашій команді зазвичай ми поєднуємо використання обох підходів в одному проекті, і навіть іноді при розробці одного блоку коду.

Ну, наприклад, коли ми пишемо частина проекту для роботи з сервісами через API, ми пишемо спочатку тести і вже потім код (TDD). Однак після реалізації часто буває так, що написаних завчасно тестів недостатньо і доводиться їх дописувати, досягаючи 100% покриття (TLD).

Іноді навіть на дуже прості контролери (звичайний ресурс з базовими CRUD), спочатку пишуться прості тести, а потім уже код (TDD). Це дає нам впевненість в тому, що нічого не забуто в первісній реалізації. Надалі, при розвитку проекту, в більшості випадків тести пишуться вже після написання коду (TLD).

Часто є завдання реалізації алгоритму на відомі вхідні/вихідні дані, тут теж в основному використовується TDD підхід. Якщо є готові вхідні і вихідні дані, то за ним дуже легко написати простий тест, а вже потім реалізувати цей алгоритм, будучи впевненим у результаті.

Найчастіше TLD підхід застосовується під час рефакторінгу. Спочатку ми покриваємо тестами існуючу реалізацію і вже потім переписуємо її.

Якщо говорити про співвідношення використання TDD і TLD в проектах, то виграє зазвичай TLD. Розробників, які просто пишуть тести завжди більше, ніж тих, хто в стані «думати тестами» і писати тести завчасно.
Джерело: Хабрахабр

0 коментарів

Тільки зареєстровані та авторизовані користувачі можуть залишати коментарі.