Чи має значення додавання одиничних тестів для відомого старого коду?


21
  • Я говорю про одиничні тести в сенсі TDD. (Не автоматизована "інтеграція", або те, що ви хочете називати це тестами.)
  • Старий код як у: (C ++) код без тестів. (див.: Майкл Пірс " Ефективна робота зі спадковим кодексом )"
  • Але також застарілий код, як у: Код, з яким працює наша команда останні 10-5 років, тому ми дуже часто маємо досить гарне уявлення про те, куди подіти речі, щоб щось змінити.
  • У нас є одиничні тести (через Boost.Test) для деяких модулів, які з’явились пізніше або були "природним" пристосуванням для тестових одиниць (звичайні контейнери, додатки для рядків, мережеві помічники тощо)
  • Ми ще не маємо належних автоматизованих тестів на прийняття.

Зараз нещодавно мені випало задоволення реалізувати 3 нові функції, орієнтовані на користувачів.

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

Тепер я дійсно додав мало коду. (Я думаю, що один метод і кілька ліній дзвінків для кожної функції.)

Розроблення цього коду (за допомогою будь-якого із методів, запропонованих у WEwLC ), так що одиничний тест мав би сенс (а не був повною тавтологією) легко зайняв би ще 2-4 години, якби не більше. Це додало б 50% -100% часу до кожної функції, без негайної вигоди, як

  1. Мені не потрібен був тестовий пристрій, щоб щось зрозуміти про код
  2. Тестування вручну - це та ж робота, яку мені ще потрібно перевірити, чи правильно інтегровано код у решту програми.

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

Отже, "цього разу" я вирішив не робити важкої роботи над додаванням одиничного тесту: Зміни коду для отримання цих тестів були б значно складнішими, ніж зміни коду для правильної (та чистої) реалізації функції.

Це щось типове для сильно пов'язаного застарілого коду? Я лінивий / чи ми встановлюємо неправильні пріоритети як команда? Або я розсудливий, лише тестую речі, коли накладні витрати не надто великі?


що робити, якщо якийсь інший відділ візьме на озброєння ваш «добре відомий спадковий код»? Що хлопці там з цим робитимуть?
Олексій Теодорідіс

Відповіді:


18

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

Я б завжди сперечався з приводу нового коду, але, за старим кодом, ви повинні робити виклик судження.

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

Правило: Завжди думайте про себе: " Чи вважаю я, що бізнес отримує більше користі від цієї технічної роботи, яку я вважаю, що повинен зробити, ніж ту роботу, яку вони просили, і в результаті вона буде відкладена? "


Що таке хороший фрагмент коду? Той, що добре розроблений, перевірений, задокументований та надалі підтверджений, або той, що вам платять? Як завжди: ти можеш мати це добре ; ви можете це дешево ; ви можете це швидко . Виберіть будь-які два, третій - це ваша вартість.
Сардатріон

2
"Я б завжди сперечався про новий код" ... "новий код" у застарілій базі коду чи "новий новий код"? :-)
Мартін Бат

pdr має правильну ідею. Це інженерне рішення (одне із компромісами). Як правило, якщо у вас є великий шматок перевіреного коду, це гарна ідея залишити його в спокої. Я бачив зусилля TDD щодо застарілого коду (всього на рік, але цього достатньо), і в кінцевому рахунку витрачаються місяці, і лише в кінцевому рахунку витрачаються гроші та ламаються застарілий додаток протягом місяців, поки помилки, внесені TDF-рефактором, не були виправлені. Якщо код / ​​функція зроблена і протестована, не переривайте її, додаючи інструментарію (TDD), щоб сказати вам щось, що ви вже все-таки знали (що це працює).
анонім

10

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

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

Якщо ви хочете, щоб ваш проект вижив, ви повинні підготувати його до змін.


3

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

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


1
Але, але, але! :-) Це трохи має Зрушення до збільшення 100% часу , необхідного для реалізації нової функції. Це не зменшує час, необхідний для впровадження наступних функцій. Це може зменшити час, необхідний для зміни матеріалів.
Мартін Ба

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

1
@Martin, тому що чітко те, що ви робите, - це кодування того, що, на вашу думку, має бути функцією, а потім відправте його. Тестування взагалі не робиться на жодному етапі ... ні, зачекайте. Як розробники, ми перевіряємо наш код (принаймні вручну), перш ніж говорити, що це зроблено. Заміна "від руки" на "написання автоматизованого тесту" не є 100% збільшенням часу. Часто я вважаю, що це приблизно той самий час, який приймають.
Kaz Dragon

1
@Kaz - "Заміна" вручну "на" написання автоматизованого тесту "не є на 100% збільшенням часу. Часто я вважаю, що це приблизно той же час, що займається". - YMMV, але для моєї кодової бази це явно неправильно (як викладено у запитанні).
Мартін Ба

3
@Kaz: Що я мав на увазі :-) мав на увазі: тестовий блок перевіряє мій код ізольовано. Якщо я не пишу одиничний тест, я не перевіряю код поодиноко, але лише якщо код названо правильно і приносить бажаний результат у програмі. Ці два моменти (називається правильно і додаток робить те, що потрібно) я все одно повинен перевірити (вручну) і не охоплений одиничним тестом. І тест одиниці не охоплював би ці два бали, а "просто" перевіряв би мою функцію ізольовано. (І ця тестова одинична перевірка була б додатковою і не компенсувалась нічим, наскільки я бачу.)
Мартин Ба,

2

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

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

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


1

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

Так, на написання одиничного тестування це може коштувати ще 2-3 години, але якщо код повернеться з тестування, вам доведеться ще раз вручну протестувати все та документувати тестування - чи не так? Інакше як хто знає, що ви протестували та які значення використовували?

Блок тестів задокументує очікувану поведінку коду, тестові дані, які використовуються для перевірки функціональності, і надають новим кодерам розумну впевненість, що вони щось не зламали під час внесення змін.

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

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


"і знову задокументуйте тестування - зробите це, чи не так?" - {надягаючи цинічну шапку:} Звичайно, ні. Ми не в землі казкових розробників. Речі реалізовуються та перевіряються та постачаються. Пізніше він розбивається та фіксується, а також перевіряється та відправляється.
Мартін Ба

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

2
mcottle - Вам не вистачає життєвої точки. Тестування пристрою не зменшить час, необхідний для "ручного тестування функціональності" готової функції. Мені все ж доведеться переглядати всі діалогові вікна, що стосуються розсудливого набору можливих входів, щоб переконатися, що фактично готовий додаток як вбудований робить те, що він повинен робити. (Я дозволю, що теоретично одиничне тестування може допомогти обмежити цей цикл ручного тестування лише однією циклом, якщо одиничні тести переконуються, що я не знайду жодної очевидної проблеми лише під час ручного тестування.)
Мартін Ба,

0

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

Так, можливо, вам доведеться витратити те, що здається непомірною кількістю часу, щоб зробити застарілий код перевіреним.

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


1
"Без тестових одиниць у вас немає жодних інших засобів для того, щоб ваша функція не була ненавмисно порушена, навіть коли сама ця функція не була змінена" - Тестові одиниці не допоможуть. Щоб переконатися , мені доведеться провести автоматизовані тести на інтеграцію / прийняття.
Мартін Ба

Так, одиничні тести - це лише перший крок. Відредагована відповідь для уточнення
Мар'ян Венема
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.