Чи може бути тестування одиниць успішно додано до існуючого виробничого проекту? Якщо так, то як і чи варто це?


140

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

Читаючи подібні запитання на SO, я бачив такі рекомендації, як запуск у трекері помилок та написання тестового випадку для кожної помилки для запобігання регресії. Однак я стурбований тим, що в кінцевому підсумку я пропущу велику картину і пропущу фундаментальні тести, які були б включені, якби я використовував TDD з початку роботи.

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

Тому я здогадуюсь, про що я також прошу;

  • Чи варто докладати зусиль для існуючого рішення, яке знаходиться у виробництві?
  • Чи було б краще проігнорувати тестування для цього проекту та додати його у можливій майбутній переписці?
  • Що буде кориснішим; витративши кілька тижнів на додавання тестів або кілька тижнів на додавання функціональності?

(Очевидно, що відповідь на третій пункт повністю залежить від того, ви спілкуєтесь з керівництвом чи розробником)


Причина Баунті

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

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


11
Обов’язкове посилання на книгу Майкла Пір'я на тему: amazon.com/Working-Effectively-Legacy-Michael-Feathers/dp/…
Mark Rushakoff

1
@Mark - Спасибі, це у посиланні, яке я надав. Я сподівався отримати гідну відповідь, не купуючи іншої книги ... хоча ви ніколи не можете мати занадто багато книг (якщо тільки ви не хочете, щоб це було зроблено).
djdd87

1
Вам справді потрібно прочитати цю книгу :) Це одна з моїх улюблених і справді допомагає зрозуміти напругу між рефакторингом та автоматизованим тестуванням.
manuel aldana

Відповіді:


177

Я ввів модульні тести в кодові бази, які раніше не були. Останній великий проект, з яким я брав участь, де я робив цей продукт, вже був у виробництві з нульовими тестовими одиницями, коли я прибув до команди. Коли я пішов - через 2 роки - у нас було 4500+ або більше тестів, що дало близько 33% покриття коду в кодовій базі з 230 000 + LOC виробництва (фінансовий додаток Win-Forms у режимі реального часу). Це може здатися низьким, але результатом було суттєве поліпшення якості коду та швидкості дефектів - плюс покращення моралі та рентабельності.

Це можна зробити, коли ви маєте як точне розуміння, так і відданість сторонам, які беруть участь у цьому.

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

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

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

Тепер для ваших коментарів та питань:

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

Коротка відповідь: Так, ви пропустите тести, і так, вони, можливо, спочатку не будуть схожі на те, що вони мали б у ситуації із зеленим полем.

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

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

Знову ж таки, це вміння. Не можна переходити від нульових тестів до TDD-досконалості одним «процесом» або «поетапним» приготуванням книжкового підходу лінійним способом. Це буде процес. Ваші очікування повинні полягати в поступовому та поступовому прогресі та вдосконаленні. Чарівної таблетки немає.

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

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

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

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

Тренуйте своїх людей.

Почніть десь і почніть додавати тести, поки ви прогресуєте з точки зору замовника (див. Нижче).

Використовуйте покриття коду як орієнтир про те, яка частина вашої виробничого коду знаходиться на тесті.

Час нарощування завжди повинен бути швидким. Якщо час збирання повільний, навички тестування одиниць відстають. Знайдіть повільні тести та вдосконаліть їх (відокремте виробничий код та випробування ізольовано). Добре написано, вам слід легко мати кілька тисяч одиничних тестів і все-таки завершити збірку за 10 хвилин (~ 1 - кілька мс / тест - це хороша, але дуже груба інструкція. Можливо, застосовуються деякі винятки, такі як код за допомогою відображення тощо. ).

Перевірити та адаптувати.

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

Ваше власне судження повинно бути вашим першоджерелом реальності. Немає метрики, яка може замінити майстерність.

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

Два грубі вторинні показники - це загальне покриття коду та швидкість збирання.

Чи варто докладати зусиль для існуючого рішення, яке знаходиться у виробництві?

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

Чи було б краще проігнорувати тестування для цього проекту та додати його у можливій майбутній переписці?

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

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

Що буде кориснішим; витративши кілька тижнів на додавання тестів або кілька тижнів на додавання функціональності?

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

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

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

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

Що ви робите, це погашення технічної заборгованості. І ви це робите, все ще обслуговуючи своїх клієнтів, постійно змінюючи потреби. Поступово, коли борг погашається, ситуація покращується, і легше обслуговувати замовника і доставляти більше вартості. І т. Д. Цей позитивний імпульс - це те, до чого слід прагнути, оскільки він підкреслює принципи стійкого темпу і підтримуватиме та вдосконалює мораль - як для вашої команди розвитку, так і для клієнта та ваших зацікавлених сторін.

Сподіваюся, що це допомагає


Відображає такий же спосіб мислення, як і я. В даний час я демонструю цей точний процес / метод для впровадження тестових випадків у великому додатку JAVA. :)
Даршан Джоші

3
Це найкраща сформульована відповідь на будь-яку тему, яку я коли-небудь читав на Stackoverflow. Молодці! Якщо ви цього не зробили, я б закликав вас розглянути можливість написання книги на вашу відповідь на останнє запитання.
Yermo Lamers

Дякую, Єрмо. Я не впевнений, чи маю час написати книгу. Але, можливо, я міг написати статтю або дві статті блогу. Тільки починаю мій новий блог, тож може пройти якийсь час.
Mahol25

2
Ця порада для тестування підрозділів для хлопців - це загальна життєва порада. Серйозно.
Wjdavis5

24
  • Чи варто докладати зусиль для існуючого рішення, яке знаходиться у виробництві?

Так!

  • Чи було б краще проігнорувати тестування для цього проекту та додати його у можливій майбутній переписці?

Немає!

  • Що буде кориснішим; витративши кілька тижнів на додавання тестів або кілька тижнів на додавання функціональності?

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

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

Потім поставте тест на кожну поточну помилку у вашій базі даних про помилки, яка точно індукує помилку і яка пройде, коли помилка виправлена. Тоді виправте ці помилки! :-)

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


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

15

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

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


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

13

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

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

  • Скільки часу знадобиться, щоб ви перевірили весь цей код? Дні? Тижні? Місяці? Роки?
  • Для кого ви пишете цей код? Платять клієнти? Професор? Проект з відкритим кодом?
  • Який у вас графік? У вас є жорсткі терміни, які ви повинні дотримуватися? У вас взагалі є якісь терміни?

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

  • Будь-який новий код, який ви пишете, повинен повністю перевірятися
  • Будь-який старий код, до якого ви стикаєтесь (виправлення помилок, розширення тощо), слід поставити під тест одиниці

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

Редагувати:

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

Це як запитання "Які плюси та мінуси використання керування джерелами?" або "Які плюси і мінуси опитувати людей перед тим, як їх наймати?" або "Які плюси і мінуси дихання?"

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


9

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

Одним з перших, що ми зробили (після налаштування сервера безперервного збирання) було додавання тестів регресії. Це були випробування наскрізь.

  • Кожен тестовий набір починається з ініціалізації бази даних до відомого стану. Насправді у нас є десятки регресійних наборів даних, які ми зберігаємо в Subversion (в окремому сховищі від нашого коду, через розмір). FixtureSetUp кожного тесту копіює один із цих наборів регресії в базу даних temp, а потім працює звідти.
  • Потім налаштування тестового кріплення запускає певний процес, результати якого нас цікавлять. (Цей крок необов’язковий - деякі тести регресії існують лише для тестування звітів.)
  • Потім кожен тест запускає звіт, виводить звіт у файл .csv та порівнює вміст цього .csv із збереженим знімком. Ці знімки .csvs зберігаються в Subversion поруч із кожним набором регресії. Якщо вихідний звіт не відповідає збереженому знімку, тест завершується невдаче.

Мета регресійних тестів - сказати вам, чи щось зміниться. Це означає, що вони виходять з ладу, якщо ви щось зламали, але вони також не вдається, якщо ви щось змінили спеціально (у такому випадку виправлення полягає в оновленні файлу знімка). Ви не знаєте, що файли знімків навіть правильні - в системі можуть виникнути помилки (і тоді, коли виправите ці помилки, тести регресії не вдасться).

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

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

Регресійні тести мають проблеми: вони повільні, і є занадто багато причин, через які вони можуть зламатися. Але принаймні для нас вони так варті. Вони зловили незліченну кількість помилок за останні п’ять років, і вони їх ловили протягом декількох годин, а не чекали циклу QA. У нас ще є оригінальні регресійні тести, які розповсюджуються на сім різних машин безперервного збирання (окремо від тієї, яка виконує тести швидкого блоку), і ми навіть додаємо їх час від часу, тому що у нас все ще стільки коду, що наші 6000 + одиничні тести не охоплюють.


8

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

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

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


6

Я додам свій голос і скажу так, це завжди корисно!

Однак слід пам’ятати про деякі відмінності: «чорний ящик» проти «білого поля» та «модуль проти функціоналу». Оскільки визначення різняться, ось що я маю на увазі під цим:

  • Black-box = тести, написані без спеціальних знань щодо впровадження, як правило, стикаються з краєм справ, щоб переконатися, що все відбувається так, як очікував би наївний користувач.
  • Біла скринька = тести, написані зі знанням реалізації, які часто намагаються реалізувати відомі точки відмови.
  • Тестові одиниці = тести окремих одиниць (функцій, роздільних модулів тощо). Наприклад: переконайтеся, що клас масиву працює так, як очікувалося, і що ваша функція порівняння рядків повертає очікувані результати для широкого спектру входів.
  • Функціональні тести = тести всієї системи відразу. Ці тести дозволять отримати великий шматок системи відразу. Наприклад: init, відкрити з'єднання, зробити якісь реальні речі, закрити, припинити. Мені подобається робити різницю між цими та одиничними тестами, оскільки вони служать різному призначенню.

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

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

Як і інші, я також нагадаю вам про дві найважливіші речі щодо TDD:

  1. Створення тестів - це безперервна робота.Це ніколи не зупиняється. Вам слід намагатися додавати нові тести кожного разу, коли ви пишете новий код або змінюєте існуючий код.
  2. Ваш тестовий набір ніколи не є непогрішним! Не дозволяйте тому, що у вас є тести, втягує вас у помилкове почуття безпеки. Тільки те, що він проходить тестовий набір, не означає, що він працює правильно, або що ви не ввели тонкої регресії продуктивності тощо.

4

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

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

Моя відповідь на ваше третє запитання така ж, як і на перше: це залежить від контексту вашого проекту.

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


4

Ви не згадуєте мову реалізації, але якщо в Java тоді ви можете спробувати такий підхід:

  1. У окремому дереві вихідного дерева будують регресію або "димові" тести, використовуючи інструмент для їх генерування, який може отримати близько 80% покриття. Ці тести виконують всі логічні коди коду і з цього моменту підтверджують, що код все ще робить саме те, що він робить в даний час (навіть якщо помилка присутня). Це дає вам безпечну мережу від ненавмисного зміни поведінки під час виконання необхідного рефакторингу, щоб зробити код легко ручним для перевірки.

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

  3. Існуючий код також, ймовірно, потрібно буде змінити або відновити, щоб зробити його тестуваним як частину додавання нових функцій; ваші тести на дим дадуть вам захисну сітку від регресу чи ненавмисних тонких змін у поведінці.

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

  5. Під час виправлення помилок напишіть невдалий тест одиниці, який спочатку виявляє помилку.


3

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

Визначте проекти проектів / модулів, де помилки були повторно введені. почніть з цих проектів, щоб написати тести. Це ідеально має сенс писати тести на нову функціональність та на виправлення помилок.

Чи варто докладати зусиль для існуючого рішення, яке знаходиться у виробництві?

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

Чи було б краще проігнорувати тестування для цього проекту та додати його у можливій майбутній переписці?

Я б рекомендував почати, якщо відтепер.

Що буде кориснішим; витративши кілька тижнів на додавання тестів або кілька тижнів на додавання функціональності?

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


3

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

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


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

2

Так, це може: просто спробуйте переконатися, що весь код, який ви зараз пишете, має тест.

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


2

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

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

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


2

Оновлення

Через 6 років після оригінальної відповіді я маю дещо іншу думку.

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

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

Рання відповідь

Я збираюся тут підняти кілька брів :)

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

Однак, якщо ви працюєте над додатком, який, ймовірно, вимагатиме змін у функціональності (через зміну вимог), тоді немає ніякого сенсу докладати додаткових зусиль.

Чому?

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

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

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

  4. Експериментальні випробування не вплинуть на сприйману якість вашого продукту - на якість, яку бачить користувач. Звичайно, ваші методи можуть працювати точно так само, як і в перший день, інтерфейс між шаром презентації та бізнес-шаром може бути незайманим - але здогадайтесь, що? Користувача це не хвилює! Отримайте справжні тестери для тестування вашої програми. І частіше за все ці методи та інтерфейси доводиться все-таки змінювати, рано чи пізно.

Що буде кориснішим; витративши кілька тижнів на додавання тестів або кілька тижнів на додавання функціональності? - Є пекло багато речей, які можна зробити краще, ніж писати тести - Пишіть нові функціональні можливості, покращуйте продуктивність, підвищуйте зручність використання, пишіть кращі довідкові посібники, вирішуйте очікувані помилки тощо.

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


І я закликаю вас прочитати це - joelonsoftware.com/items/2009/01/31.html
Roopesh Shenoy

Ви хочете "виправити помилки, що очікують", або запобігти їх виникненню? Правильне тестування пристрою дозволяє економити час, зводячи до мінімуму кількість часу, витраченого на виправлення помилок.
Ігор Кахарліченко

Це міф. Якщо ви говорите мені, що автоматичні тестові одиниці є заміною для ручного тестування, ви серйозно помиляєтесь. І що реєструють ручні тестери, якщо не помилки?
Roopesh Shenoy

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

1

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

  • Як ви вже згадували, коли ви знайдете помилку, це найкращий час написати тест (відтворити його), а потім виправити помилку. Якщо ви бачите, що тест відтворює помилку, ви можете бути впевнені, що це хороший тест alid. Враховуючи, що така велика частина помилок - це регресії (50%?), Майже завжди варто писати тести на регресію.
  • Коли ви занурилися в область коду, щоб змінити його, настав час написати тести навколо нього. Залежно від природи коду підходять різні тести. Тут знайдеться один гарний набір порад .

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

Удачі!



1

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

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

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

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


1

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

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

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

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

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


1

Є дуже багато хороших відповідей, тому я не буду повторювати їх зміст. Я перевірив ваш профіль і, здається, ви розробник C # .NET. Через це я додаю посилання на проект Microsoft PEX та Moles, який може допомогти вам з автоматичною генерацією тестів для застарілого коду. Я знаю, що автогенерація - це не найкращий спосіб, але принаймні це шлях до початку. Перегляньте цю дуже цікаву статтю журналу MSDN про використання PEX для застарілого коду .


1

Я пропоную прочитати геніальну статтю TopTal Engineer, яка пояснює, з чого почати додавати тести: вона містить багато математики, але основна ідея:

1) Виміряйте Аферентну з’єднаність вашого коду (CA) (наскільки клас використовується в інших класах, тобто його порушення спричинить широкий збиток)

2) Виміряйте цикломатичну складність коду (CC) (більша складність = більша зміна розриву)

Вам потрібно ідентифікувати класи з високим рівнем CA та CC, тобто мати функцію f (CA, CC), а класам з найменшими різницями між двома показниками слід надавати найвищий пріоритет для тестового покриття.

Чому? Оскільки високий рівень CA, але дуже низький клас CC є дуже важливим, але навряд чи може порушитися. З іншого боку, низький рівень CA, але високий КК, швидше за все, порушиться, але спричинить менший збиток. Отже, ви хочете збалансувати.


0

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


-2

Так. Ні. Додавання тестів.

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

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