Чи є таке поняття, як занадто багато одиничних тестів?


139

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

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

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

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

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


145
Це залежить. Ви пишете гру з тик-так-носком чи пишете код для управління ядерним реактором?
Брайан Оуклі

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

5
Тестування на вищих рівнях забезпечить вам кращу перспективу реального покриття. Під реальним покриттям я маю на увазі те, що частіше трапляється під час регулярного використання системи. Це те саме покриття, яке ви хочете досягти спочатку. У 50% тих, хто останній може досягти, може бути YAGNI або мертвий код, який після вилучення також сприятиме збільшенню загального покриття.
Лаїв

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

12
Документ тестування sqlite - це цікаве прочитання: sqlite.org/testing.html . Цитата: "Бібліотека SQLite складається приблизно з 122,9 KSLOC коду С. Для порівняння, проект має в 745 разів більше тестового коду та тестових сценаріїв - 91596,1 KSLOC."
user60561

Відповіді:


180

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

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

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


11
Дякую за вашу відповідь. Це допомогло поставити моє питання в перспективу і вирішило реальну проблему - моє ставлення! +1
користувач2954463

43
@astra Ваше ставлення не так вже й погано. Добре запитати, чому. Щоб відповісти на ваше інше запитання, відмінне запитання: "Як я знаю своїх однолітків, і я поділяю ту саму ідею для" найпоширеніших випадків використання "? Ви змушуєте їх переглянути ваші тести. Подивіться на їхні. Поговоріть про них. Ви дізнаєтесь багато, і, можливо, вони теж будуть. Перегляд тестів з кодом рідко є марною
витратою

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

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

10
@Pharap Моя єдина проблема з цією відповіддю полягає в тому, що існує неявне припущення, що тест може додавати значення лише тоді, коли він не працює. Хороший одиничний тест також забезпечує чудову форму живої документації. Це також додало цінності, коли ви писали тест, змушуючи задуматися про повторне використання / компостування / інкапуляція. Неперевірений код у моєму досвіді має тенденцію бути негнучкими монолітними звірами.
ArTs

66

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

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


16
Запропоновані для вказівки на попередні умови, пост-умови та інваріанти слід розглядати як одиничне тестування. Таким чином, кожне використання є тестовою одиницею, коли цей код налагодження активний.
Persixty

Це чудова відповідь і ідеально відповідає моєму досвіду.
Тоні Енніс

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

3
Це набагато краща відповідь, ніж прийнята! "У деяких випадках більша частина зусиль з розробки складається з оновлення неякісних тестів" - я пережив це, і це відстійно. В деяких відношеннях взагалі немає тестів.
Бенджамін Ходжсон

36

Відповіді на ваші запитання

Чи є таке поняття, як занадто багато одиничних тестів?

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

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

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

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

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

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

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

Це правильно для "одиничних" тестів у строгому сенсі. Тут «одиниця» є чимось на зразок методу чи класу. Суть "одиничного" тестування полягає в тестуванні лише однієї конкретної одиниці коду, а не всієї системи. В ідеалі ви видалите всю іншу частину системи (використовуючи подвійні чи щось таке).

Однак у запиті на виклик мій технічний керівник зазначив, що я повинен зосередитися на тестуванні вищого рівня.

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

Він запропонував протестувати 4-5 випадків використання, які найчастіше використовуються з відповідним класом, а не вичерпно перевіряти кожну функцію.

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

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

Я не знаю, що таке "одиничне покриття тесту". Я припускаю, що ви маєте на увазі "охоплення кодом", тобто що після запуску тестового набору кожен рядок коду (= 100%) був виконаний принаймні один раз.

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

Інтеграційне тестування

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

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

Вони йдуть рука об руку з розвитком, керованим поведінкою або розвитком функцій; вони не працюють із (суворими) одиничними тестами, за визначенням.

Щоб зробити його коротким (ish), тест на інтеграцію / функціональність виконує весь стек програм. У веб-додатку це буде діяти як браузер, натискаючи на додаток (і ні, очевидно, це не повинно бути таким спрощеним, для цього є дуже потужні рамки - перевірити http: // cucumber). io для прикладу).

О, щоб відповісти на ваші останні запитання: ви отримуєте всю команду, яка має високий рівень тестового покриття, переконуючись, що нова функція запрограмована лише після того, як її тест функцій було впроваджено та не вдалося. І так, це означає кожну особливість. Це гарантує вам 100% (позитивне) покриття функції. Це за визначенням гарантує, що функція вашої програми ніколи не «згасне». Це не гарантує 100% покриття коду (наприклад, якщо ви активно не запрограмуєте негативні функції, ви не будете здійснювати обробку помилок / обробку винятків).

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

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


1
Інтеграційні тести чудові, але не є заміною для одиничних тестів, також не для ділових додатків. З ними виникає чимало проблем: а) за визначенням вони потребують тривалого часу (це також означає, що додаткові тести дуже марні); б) їм важко точно визначити фактичну проблему (ох 50 інтеграційних тестів просто не вдалося, яка зміна викликала це?) і в) вони неодноразово висвітлюють одні й ті ж кодові шляхи.
Ву

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

1
@Voo, все, що ви написали, - це правда, і наскільки я можу сказати, я вже згадував усі проблеми, які ви відзначили у відповіді ...
AnoE

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

24

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

Деякі сценарії:

  1. Ви надмірно розробляєте свої тести для конкретної реалізації. Тоді вам доведеться викидати тести блоку, коли ви рефактор, не кажучи, коли ви змінюєте реалізацію (дуже часта больова точка при виконанні оптимізації продуктивності).

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

  2. Ви можете мати розумне покриття для кожної комісії з 20% ваших тестів, залишаючи решту 80% для інтеграції або хоча б окремих пробних тестів; Основні негативні наслідки, які ви бачите в цьому сценарії, - це повільні зміни, оскільки вам доведеться чекати тривалий час, щоб виконати тести.

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

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


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

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

Я люблю ваш опис @johncip, безумовно, це частий приклад того, як хороший клас стає жахливим, додавши конструктору купу непотрібних необхідних параметрів ...
Bruno Guardia

19

Майте на увазі, що кожен тест має вартість, а також користь. До недоліків можна віднести:

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

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

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


12

Так, є таке поняття, як занадто багато одиничних тестів.

Хоча тестування добре, кожен одиничний тест:

  • Потенційне навантаження на обслуговування, що щільно пов'язане з API

  • Час, який можна було б витратити на щось інше

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

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

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

Прагматика більшості кодів вказує на:

  1. Переконайтеся, що ви маєте 100% охоплення вхідних точок (усе тестується якось) і прагніть бути близьким до 100% покриття коду шляхів "без помилок".

  2. Перевірте будь-які відповідні значення / розміри min / max

  3. Перевірте все, що вам здається, смішним особливим випадком, особливо «непарними» значеннями.

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

Для більш складних алгоритмів врахуйте також:

  1. Здійснюємо об'ємне тестування більшої кількості справ.
  2. Порівнюючи результат із реалізацією «грубої сили» та перевіряючи інваріанти.
  3. Використовуючи певний метод виготовлення випадкових тестових випадків та перевірки на грубі сили та пост-умови, включаючи інваріанти.

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

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

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

Ключовим уроком є ​​додавання тестів при виявленні помилок. Це підводить мене до найкращого уроку з розробки одиничних тестів:

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

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

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

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


4
Я б не сказав, що 100% охоплення є прагматичним. 100% покриття - надзвичайно високий стандарт.
Брайан Оуклі

На жаль, навіть рандомізований метод може пропустити помилки. Доказів не існує, навіть якщо вони неофіційні.
Френк Хілеман

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

@FrankHileman Питання полягало не в тому, "чи є тестування пристрою гарною заміною для ретельного проектування програмного забезпечення, статичної перевірки логіки та доведення алгоритмів", тоді відповідь - "ні". Жоден із способів не виробляє високоякісне програмне забезпечення самостійно.
Persixty

3

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

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

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

Наступні найцінніші тести - це ті, які здійснюють граничні межі або граничні точки. Наприклад, функцію, яка приймає місяці року на основі 1, слід перевірити з 0, 1, 12 і 13, так що ви знаєте, що дійсні-недійсні переходи знаходяться в потрібному місці. Це занадто тестування, щоб також використовувати 2..11 для цих тестів.

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


3

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

Це розуміння неправильне.

Одиничні випробування перевіряють поведінку досліджуваної одиниці .

У цьому сенсі одиниця не обов'язково є "методом у класі". Мені подобається визначення одиниці Роя Ошерова в «Мистецтві тестування одиниць» :

Одиниця - це весь виробничий код, який має однакові причини зміни.

Виходячи з цього, блок-тест повинен перевірити кожну бажану поведінку вашого коду. Де «бажання» більш-менш взято з вимог.


Однак у запиті на виклик мій технічний керівник зазначив, що я повинен зосередитися на тестуванні вищого рівня.

Він правий, але по-іншому, ніж він думає.

З вашого запитання я розумію, що ви - "відданий тестер" у цьому проекті.

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

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

Щоб ще раз підкреслити аналогію автомобіля звалища: скільки тестів робиться з автомобілем в кінці конвеєрної лінії? Саме одна: вона повинна під'їхати до парковки сама по собі ...

Сенс у цьому:

Нам потрібно знати, що різниця між "одиничними тестами" та "тестовими автоматизованими за допомогою одиничної рамки тестування".


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

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

Вам не потрібно 100% покриття коду.

Але вам потрібно 100% охоплення поведінки. (Так, охоплення кодом та покриття поведінки так чи інакше співвідносяться, але вони не є ідентичними заради цього.)

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


Висновок

Мало тестів краще, ніж жодного тесту. Без сумніву!

Але немає такого поняття, як занадто багато одиничних тестів.

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


2

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

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


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

2
Це не проблема з тестами, а з організацією.
jwenting

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

2
@jwenting Так, це організаційна проблема, а не проблема коду. Але це не змінює той факт, що тестів було занадто багато. Невдалий тест, який неможливо дослідити, марний, незалежно від причини.
mrog

Що таке "SDET"?
Пітер Мортенсен

1

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

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

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


0

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

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

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

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

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