Як проводиться юніт-тест модульного тесту? [зачинено]


89

Я дивився веб-трансляції Роба Коннеріса в додатку MVCStoreFront, і помітив, що він модульно тестував навіть найповсякденні речі, такі як:

public Decimal DiscountPrice
{
   get
   {
       return this.Price - this.Discount;
   }
}

Мав би такий тест, як:

[TestMethod]
public void Test_DiscountPrice
{
    Product p = new Product();
    p.Price = 100;
    p.Discount = 20;
    Assert.IsEqual(p.DiscountPrice,80);
}

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

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

Крім того, ваш модульний тест - ще одна точка відмови:

[TestMethod]
public void Test_DiscountPrice
{
    Product p = new Product();
    p.Price = 100;
    p.Discount = 20;
    Assert.IsEqual(p.DiscountPrice,90);
}

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

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

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

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

РЕДАГУВАТИ: Кілька людей постійно згадують, що тестування допомагає застосувати специфікацію. Я бачив, що специфікація також часто помилялася, але, можливо, я приречена працювати в організації, де специфікації пишуть люди, які не повинні писати специфікації.


5
у багатьох випадках модульним тестом є специфікація, і документація теж!
Стівен А. Лоу

32
... а потім юніт-тест юніт-тест юніт-тесту ... але як щодо одиничного тесту ^ 4 та юніт ^ 5 тесту ... аааааааааххххххххх!
dacracot

14
Жодне тестування не врятує вас від неправильної специфікації.
Білл Ящірка

4
Хтось ще щойно чув, що звучало як плескання однієї руки?
gnovice 02

9
Я думаю, що відповідна цитата: "Це просто черепахи аж донизу".
Quinn Taylor

Відповіді:


63

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

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

По-третє, деякі стверджують, що TDD вирішує цю проблему. Тобто, якщо ви просто напишете 20 тестів і вони пройдуть, ви не повністю впевнені, що вони насправді щось тестують. Але якщо кожен тест, який ви написали спочатку, провалився , а потім ви його виправили, ви набагато впевненіші, що він справді тестує ваш код. ІМХО займає більше часу, ніж варто, але це процес, який намагається вирішити вашу проблему.


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

2
Ось чому ви використовуєте макетні об'єкти для тестування кожного шару окремо.
Toon Krijthe

10
Чудово, тому мій тест пройде за допомогою IMockedComplexObject, але коли я фактично використовую ComplexObject у реальному світі, це не вдається ... Я знову нічого не отримав.
FlySwat

16
@Jonathan - ні, ви набули впевненості в тому, що ваш код працює - припускаючи, що ви розробили інтерфейс ComplexObject і адекватно протестували його. У гіршому випадку ви отримали знання, що ваше розуміння ComplexObject було не таким, як ви очікували.
tvanfosson

9
@FlySwat: У відповідь на ваш коментар щодо IMockedComplexObject я цитую коментар Кваша щодо іншої відповіді: "Ви не глузуєте над тим, що намагаєтеся перевірити, ви глузуєте над тим, що не намагаєтеся перевірити".
Брайан

39

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

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

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

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

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

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


4
Неправильний тест дозволить розбитий код у дикій природі. Ось де вводиться несправність. Це забезпечує помилкове почуття впевненості.
FlySwat

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

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

2
дуже цікава відповідь.
Пітер

22

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

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

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

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


"Викликати метод із певним входом і порівняти його із очікуваним результатом." але що, якщо висновок складного типу ... як XML-документ. Ви не можете просто "==", вам доведеться написати конкретний код порівняння, і тоді, можливо, ваш метод порівняння може бути помилковим ??
andy

@andy: Ви повинні протестувати свій метод порівняння окремо. Після того, як ви його ретельно протестували, ви можете покластися на це, працюючи в інших тестах.
Білл Ящірка

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

11

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

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

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

[РЕДАГУВАТИ]

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


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

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

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

@cwash - Я не впевнений, як ваш коментар стосується моєї відповіді. Я не згадав про глузування ... і я згоден з вашим спостереженням.
tvanfosson

@tvanfosson - мій останній коментар був у відповідь на @FlySwat "... знущання над правилом як зайвим". Вибачте, я забув вказати.
cwash

10

Як тестувати тест ? Тестування мутацій - цінна техніка, яку я особисто використовував, щоб отримати напрочуд хороший ефект. Прочитайте зв’язану статтю для отримання додаткової інформації та посилань на ще більше академічних посилань, але загалом вона «перевіряє ваші тести», модифікуючи ваш вихідний код (змінивши «x + = 1» на «x - = 1», наприклад), а потім повторне тестування, переконавшись, що принаймні один тест не вдався. Будь-які мутації, які не спричиняють невдалих тестів, позначаються для подальшого дослідження.

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


1
+1 цікава концепція, про яку я ще не чув
Вім Коен

9

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

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

Assert.IsEqual(p.DiscountPrice,90);

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

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


Червоний - Зелений - Рефактор - це, щоб запам’ятати суть процесу TDD.

Червоний - це червона смужка JUnit, коли тести не вдаються.

Зелений - це колір індикатора прогресу JUnit, коли всі тести проходять.

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


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

Agile - це пряме спілкування, а не викинуті через стіну документи про вимоги.


8

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

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

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

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

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

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

До того ж, ваш юніт-тест - ще одна точка відмови ...

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

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

Що ми тут отримуємо?

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

Якщо говорити про Пір’я, то тут варто ознайомитися з двома чудовими ресурсами:

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

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

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

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

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

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

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

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

Тут слід задуматись також про те, що в минулому було доведено, що методи, принципово такі самі, як тестування, працюють: «чиста кімната» та «дизайн за контрактом», як правило, створюють однакові типи конструкцій з «мета» -кодами, які тести роблять, і застосовують такі в різних точках. Жоден з цих методів не є срібними кулями, і жорсткість в кінцевому підсумку обійдеться вам в обсязі функцій, які ви можете забезпечити з точки зору часу виходу на ринок. Але справа не в цьому. Йдеться про можливість підтримувати те, що ви робите. І це дуже важливо для більшості проектів.


7

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

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

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

5

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

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

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

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


4

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


Це не стосується жодної моєї думки. Я розумію основну мантру TDD ... Я не бачу користі.
FlySwat

4

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


3

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

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

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


3

Я бачу вашу думку, але вона явно завищена.

Ваш аргумент в основному такий: тести призводять до невдач. Тому тести є поганими / втратою часу.

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

TDD передбачає: Більше тестів = менше відмов.

Тести, швидше за все, виявляють точки невдач, ніж вводять їх.


1

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

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

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


1

Я трохи подумав про хороший спосіб відповісти на це питання і хотів би провести паралель із науковим методом. ІМО, ви можете переформулювати це запитання: "Як ви експериментуєте в експерименті?"

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

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

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


1

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

  1. Спершу напишіть свої тести.
  2. Переконайтеся, що вони не можуть почати з.
  3. Нехай вони пройдуть.
  4. Перевірте код перед тим, як реєструвати свій код (переконайтеся, що тести переглядаються.)

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


0

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

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

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