Чи є покриття тестом адекватним показником якості коду?


20

Якщо у мене є якийсь код, який має 80% тестового покриття (всі тести пройшли), чи справедливо сказати, що він більш високої якості, ніж код без тестового покриття?

Або справедливо сказати, що це більш рентабельне?


2
100% покриття не означає, що воно було добре перевірене. Але 0% означає, що його взагалі не перевіряли.
mouviciel

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

@JoeRounceville Я не впевнений ... Я можу досягти високого тестового покриття під час тестування нічого справді корисного. Покриття лише показує, яка частина коду торкається тестового набору, а не тестові значення тестів.
Андрес Ф.

1
@AndresF. Тому я сказав «технічно ні, практично так». Люди не ідіоти (як правило). Вони не (як правило) не перевіряють лише випадки, коли це не сприймає. Отже, виходячи з досвіду , багато магазинів зупиняються десь на 80% покриття, роблячи (досить безпечне) припущення, що їхні люди не дебіли.
Calphool

Відповіді:


24

У строгому сенсі не справедливо пред'являти будь-які претензії, поки не буде встановлено якість тестового набору. Здавання 100% тестів не має сенсу, якщо більшість тестів є тривіальними або повторюваними між собою.

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

Для вдосконалення тестових конструкцій ви можете використовувати (1) техніку білого поля, (2) техніку blackbox та (3) тестування на мутацію.

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

  • Чи називається кожна функція? [Функціональне покриття]
  • Чи виконується кожна заява? [Покриття заяви - І функціональне покриття, і висвітлення заяви дуже важливі, але краще, ніж нічого]
  • Чи маєте ви кожне рішення (наприклад, ifчи while) тест, який змушує його бути правдивим, та інше, яке змушує його бути помилковим? [Покриття рішення]
  • Для кожної умови, яка є сполучником (використовує &&) або диз'юнкцією (використовує ||), чи має кожна субэкспрессия тест там, де це правда / хибність? [Стан покриття]
  • Покриття циклу: чи є у вас тест, який змушує 0 ітерацій, 1 ітерації, 2 ітерацій?
  • Чи кожен breakз петлі покритий?

(2) Технології Blackbox використовуються, коли вимоги є, але сам код - ні. Це може призвести до високоякісних тестів:

  • Чи охоплюють ваші тести на чорному блоці кілька цілей тестування? Ви хочете, щоб ваші тести були «жирними»: вони не лише перевіряють функцію X, але й перевіряють Y і Z. Взаємодія різних функцій - це прекрасний спосіб знайти помилки.
  • Єдиний випадок, коли ви не хочете "жирових" тестів, це тестування стану помилок. Наприклад, тестування недійсного введення користувача. Якщо ви намагалися досягти декількох недійсних цілей тестування введення (наприклад, недійсний поштовий індекс та недійсна адреса вулиці), ймовірно, один випадок маскує інший.
  • Розглянемо типи введення та сформуємо "клас еквівалентності" для типів входів. Наприклад, якщо ваш код перевіряє, чи є трикутник рівностороннім, тест, який використовує трикутник зі сторонами (1, 1, 1), ймовірно, знайде ті самі види помилок, що і дані тесту (2, 2, 2) та (3, 3, 3) знайдемо. Краще витратити свій час на роздуми про інші класи введення. Наприклад, якщо ваша програма обробляє податки, вам потрібно перевірити кожну податкову категорію. [Це називається розділенням еквівалентності.]
  • Особливі випадки часто пов’язані з дефектами. Ваші тестові дані також повинні мати граничні значення, такі як ті, що знаходяться над, над або під ребрами завдання еквівалентності. Наприклад, тестуючи алгоритм сортування, вам потрібно буде протестувати порожній масив, масив з одним елементом, масив з двома елементами, а потім дуже великий масив. Ви повинні розглядати крайові випадки не лише для введення даних, але і для виводу. [Це аналіз граничного значення виклику.]
  • Ще одна методика - "помилка вгадування". У вас є почуття, якщо ви спробуєте якусь особливу комбінацію, яку ви можете змусити програму розбити? Тоді просто спробуйте! Пам'ятайте: Ваша мета - знайти помилки, а не підтвердити, що програма дійсна . Деякі люди вміють вгадувати помилки.

(3) Нарешті, припустимо, у вас вже є багато приємних тестів на покриття білої скриньки та застосованих методик blackbox. Що ще можна зробити? Пора перевірити свої тести . Один з методів, яким ви можете скористатися, є тест на мутацію.

Під час тестування на мутацію ви вносите модифікацію (копію) своєї програми в надії створити помилку. Мутація може бути:

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

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


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

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


7

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

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

Я знаю, який код я вважаю за краще підтримувати і розширювати.


7

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

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


3

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

Справедливо було б назвати це більш ретельним.


2

Я погодився б про підтриману частину. Нещодавно Майкл Пейзерс опублікував відео з відмінною розмовою з назвою " Глибока синергія між заповітністю та гарним дизайном ", в якій він обговорює цю тему. У розмові він каже, що відносини є одним із способів, тобто добре розроблений код є тестуваним, але тестовий код не обов'язково є добре розробленим.

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


-2

Я вже деякий час задаю собі це питання стосовно "охоплення умовами". То як щодо цієї сторінки від atollic.com "Чому аналіз покриття коду?"

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

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

У цікавій зміні перегляду Necker Cube тестовий код зараз перевіряється кодом, який перевіряється!


-3

Існує багато способів гарантувати, що програма виконує те, що ви плануєте, і гарантувати, що модифікації не матимуть ніяких ненавмисних ефектів.

Тестування - це одне. Уникнення мутації даних - це ще одне. Так це система типів. Або формальне підтвердження.

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


це лише твоя думка чи ти можеш якось підкріпити це?
гнат

2
Тестування - це не спосіб гарантувати, що програма робить те, що ви задумали.
Андрес Ф.

1
Тоді мені залишається цікаво, що таке тестування
Андреа,

@gnat це, звичайно, моя думка. І все-таки воно говорить те, що йдеться. Я взяв Haskell за приклад мови, компілятор якої дуже суворий і дає багато гарантій щодо добре сформованості введення, типів, побічних ефектів, мутації даних. Я взяв PHP як приклад мови, чий перекладач дуже м'який і який навіть не має специфікації. Навіть за відсутності тестів, наявність усіх гарантій від типів та ефектів зазвичай дає гідну ступінь надійності. Щоб компенсувати це тестами, потрібно мати дуже всебічний набір
Андреа,

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