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


86

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

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


26
Велике невірне припущення, яке ви робите, полягає в тому, що проект призначений тільки для вас і це лише зараз . Що робити, якщо залишити його на кілька місяців, зробити щось інше, а потім повернутися до цього? Чи будете ви мати таку ж впевненість у тому, щоб бути "порядним програмістом" (який не має нічого спільного з тестуванням чи ні)? Що робити, якщо хтось інший переймає ваш проект ...? Чудовий блогер (на жаль, більше не активний) написав, що завжди слід «задовольняти читача коду, а не письменника коду».
Амос М. Карпентер

6
Як щодо цього (мається на увазі для C # .NET): int x = 3 * (1/3); яке значення зберігається у x після завершення операції? Моя думка, навіть один код рядка може вимагати тестування, оскільки це може призвести до помилки, або тому, що ви цього не знаєте, або тому, що ви знаєте, але зробили неправильний код.
NoChance

2
@aaamos, я думаю, ти пропустив мою думку. Той факт, що мені задають одне це питання, свідчить про те, що я також вважаю задоволенням читача коду.
Ламін Санне

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

1
Ви ставите неправильне запитання. Не має значення, наскільки великий проект. Питання в тому, наскільки ви дбаєте, якщо це правильно? Якщо правильність важлива, одиничні тести є ефективним способом поліпшення коректності.
Марк Е. Хаазе

Відповіді:


206

Ваш проект вже досить великий.

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

    class Simple {
        boolean reallySimple() {
            return true; // how do we make sure it doesn't change to false?
        }
    }


    class SimpleTest {
        void assertReallySimple() {
            // ensure reallySimple return value isn't changed unexpectedly
            UnitTestFramework.assertTrue(new Simple().reallySimple());
        }
    }

24
Звичайно, ви повинні почати раніше, з 0 класу / 0 функціональної точки ... якщо ви слідуєте TDD :)
Kaz Dragon

115
+1. Якщо програма досить велика, щоб мати помилки, вона достатньо велика, щоб провести одиничні тести.
Джейсон Орендорф

9
@JasonOrendorff: Я знущаюся над цим плакатом і розміщую його в своєму кабінеті. Блискуча.
Джастін ᚅᚔᚈᚄᚒᚔ

Крім того, це дозволяє зробити "безпечне" рефакторинг.
Тимо

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

109

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

Що стосується мене, головними перевагами одиничного тестування є:

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

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

Число 1, як правило, достатньо, щоб зробити його варто написанням тестів. На мій досвід,> 95% коду рано чи пізно змінюється.


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

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

10
Додам, що якщо ви робите лише мінімальні автоматизовані тестування, одиничні тести мають неправильний рівень для націлювання. Натомість перейдіть на тести інтеграції / диму високого рівня, які просувають декілька наборів даних через ваше додаток до кінця, нічого не знущаючись. Ви хочете, щоб ці тести мали якомога більше вашої кодової бази та охоплювали всі звичайні випадки використання та шляхи виконання. 75% шансу дізнатися, що ваші зміни щось порушили, десь у додатку, вигідніше, ніж 5% шансу дізнатися, що ви зламали SomeClass.OneOfTheHandfulOfTestedFunctions ().
Ден Нілі

3
Ага, я думаю, ви пропустили одне: "Переконайтесь, що код працює так, як належить!"
BlueRaja - Danny Pflughoeft

3
@ BlueRaja-DannyPflughoeft: Насправді, було б точніше сказати: "Переконайтесь, що код проходить написані вами одиничні тести!"
vaughandroid

34

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

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

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


22
Програмісти, як відомо, погано оцінюють власну майстерність передбачення майбутнього
superM

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

@Jalayn Чи не є відповідь просто тим, що слід повертатися назад і додавати одиничні тести, як тільки ця реалізація вражає?
Корнел Массон

@CornelMasson Ви абсолютно праві, очікуйте, що часто важко переконати менеджерів, що "ще не закінчено", оскільки тестів не вистачає :-)
Jalayn

@Jalayn: Занадто правда!
Корнел Массон

22

Деякий час тому я знайшов приємний пост: Чому тестування приладів прискорює розвиток . Це може допомогти вам відповісти на питання.

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

У мене є «віра».

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

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

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

Майкл Перо представив в одній зі своїх книг два способи роботи зі змінами коду:

  • редагуйте і моліться,
  • охоплювати та змінювати.

Не має значення, наскільки велика база коду.


18

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

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


4
Хороший момент, і це означає, що питання ОП неправильне; чи тестування не має нічого спільного з розміром проекту. Для 5-рядкової кодової бази можуть знадобитися тести, а 1-рядковий метод у великій кодовій базі може не робити (хоча інші речі в цій кодовій базі).
Натан Лонг

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

@xaxxon: Кент насправді говорить про це в тій самій відповіді, з якою Мансуро посилався, кажучи: "Коли кодуємо команду, я змінюю свою стратегію, щоб ретельно перевірити код, який ми, як правило, помиляємося".
henko

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

5

Тестові модулі реалізовані для економії часу та вдосконалення:

  • відстеження помилок
  • рефакторинг та / або перезапис коду
  • інтеграційне тестування
  • регресійне тестування тощо.

Необхідно писати одиничні тести для відносно складних частин програми.

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


Взагалі гарна відповідь, тому +1. Однак я думаю, що у вашому заключному пункті не трапляється той факт, що ви все ще хочете / потребуєте вручну перевірити свої одиничні тести!
vaughandroid

@Baqueta, можливо, я не звучав чітко, але я не мав на увазі сказати, що одиничні тести повністю замінюють ручне тестування
superM

4

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

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


4

Якщо ви не збираєтеся писати код, не тестуючи його, ви завжди будете нести витрати на тестування.

Різниця між тестуванням одиничних тестів та відсутністю їх є різницею між витратами на написання тесту та вартістю його виконання порівняно з витратами на тестування вручну.

Якщо вартість написання одиничного тесту становить 2 хвилини, а вартість виконання тесту на одиницю становить практично 0, але вартість ручного тестування коду становить 1 хвилину, ви перериваєтесь навіть у тому випадку, коли ви провели тест двічі.


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

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

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

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


Версія TL; DR :

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

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


3

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

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

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

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


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

1
Існує принаймні два інші типи тестування - тест інтеграції та тести прийняття. Експериментальні випробування охоплюють конкретну одиницю (наприклад, ця функція цього класу повинна бути Frab the Fizz). Ви знущаєтесь / заглушуєте всі інші місця, де цей клас взаємодіє, передаючи йому дані el fake-o. Коли ви робите тести на інтеграцію, ви комбінуєте два (або більше) класів, щоб переконатися, що ваші заняття йдуть разом так, як ви вважаєте, що повинні. Врешті-решт, ви збираєте достатньо тестів, які ви робите тестування всієї системи в кінці, іноді відомі як "тести на дим".
Уейн Вернер

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

1

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

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

Цитата з "Чистого коду" Роберта К. Мартіна : "Якщо писати тривіально, тестувати банально", тож немає приводу пропускати тестування для коротких і тривіальних програм.


0

Це насправді не питання розміру - це те, що ви робите з ним (і скільки років). Якщо я обміюсь вивченням того, як працює технологія, і планую відкинути річ (у Scrum ми це називаємо шипом), я просто зашифрую, не роблячи тестування. Якщо ви плануєте розвивати його далі (навіть якщо ви просто лапшаєте навколо), вам слід написати тести навколо коду. TDD - це технологія проектування, ще до того, як це метод тестування. Ви хочете мати чітке уявлення про те, що ви хочете зробити, перш ніж зав'язатись у деталях виконання. Я б також НЕрекомендуємо спробувати написати великі одиничні тести навколо великої кількості застарілого коду. Спробуйте визначити ті складні частини (які мають високу циклічну складність / код спагетті до них) та ті частини, які часто виходять з ладу (вони часто будуть однаковими). Як підказали інші, я б хотів прочитати книгу Кента Бека на TDD і, безумовно, прочитав книгу Майкла Пера. Те, що вони не дуже охоплюють, - це політичний аспект написання одиничних тестів навколо коду. Дуже багато розробників ненавидять змінювати свій код, щоб зробити його тестируемим, а багато розробників взагалі не відчувають необхідності тестувати код. Це те, над чим ми маємо працювати, як професія. Кожна інша інженерна дисципліна зобов'язана довести (часто математично), що їх робота відповідає специфікації. Ми повинні зробити те саме.


-1

Зв'язування проектів у межах класів або функціональності, а потім судження, чи підходить це тестування для одиниць, може бути помилковим. Існує чимало переваг тестування програми, але справжня краса починається тоді, коли вам доведеться підтримувати додаток або працювати в розподіленому середовищі. Тож вибір приходить сюди. Навіть невелика зміна коду може спричинити катастрофи.
Я б не лише запропонував «Тестування одиниць», але також рекомендував би перевірити покриття коду, гарантуючи, що максимум вашого коду покрито Тестовим модулем. Поріг покриття коду не повинен бути менше 95%, а цільовий показник повинен становити близько 100% . Ви можете скористатися інструментами для відстеження покриття коду та створення звіту.
Visual Studio надає дані покриття -http://msdn.microsoft.com/en-us/library/ms182496(v=vs.80).aspx
Також можна використовувати NCover або dotCover.

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