Чому невдалі одиничні тести вважаються поганими?


93

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

Особисто я думаю, що це не так, як має бути з наступних причин:

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

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

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

  4. Це перешкоджає випробовуванню тестових модулів наперед - перед реалізацією.

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

Я чогось тут пропускаю? Чому організації очікують проходження всіх одиничних тестів? Хіба це не життя у світі мрії? І чи насправді це не стримує реального розуміння коду?


Коментарі не для розширеного обговорення; ця розмова переміщена до чату .
maple_shaft

Відповіді:


270

Це запитання містить кілька помилок, що стосуються ІМХО, але головне, на яке я хотів би звернути увагу, - це те, що воно не розмежовує між галузями місцевого розвитку, магістральними, постановочними та випусковими гілками.

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

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

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

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

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


18
Я думаю, це справжня відповідь. ОП згадує "процес випуску" та "деякий екран [показує результати тестування]", що звучить як сервер збірки. Випуск - це не те саме, що розвиток (не розвивайся у виробництві!); це добре, що провалили тести на розробці, вони схожі на TODO; всі вони повинні бути зеленими (DONE) при натисканні на сервер збірки.
Варбо

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

5
@SebastiaanvandenBroek: дякую за позитивну відповідь. Просто для того, щоб зрозуміти: невдалі випробування блоку IMHO повинні бути рідкісними навіть у багажнику, оскільки надходження таких фалій занадто часто буде турбувати всю команду, а не лише того, хто вніс зміни, які спричинили збій.
Док Браун

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

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

228

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

Це є хорошим. Ніякого "передбачається" про це.

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

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

Неприпустимо придумати тести, які не вдасться.

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

Для порівняння мислення розробника та тестера:

  • Розробник зупиняється, як тільки код виконує те, що вони хочуть.
  • Тестер зупиняється, коли вони більше не можуть зробити перерву коду.

Це кардинально різні точки зору, і багато розробників важко узгодити.

Або, звичайно, придумати тести, які було б складно виправити.

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

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

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

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

Це перешкоджає випробовуванню тестових модулів наперед - перед реалізацією.

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

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

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

Хіба це не життя у світі мрії?

У всякому разі, він живе в реальному світі , визнаючи , що розробники НЕ є ні всезнаючим , ні infallable, що ми робимо робимо помилки , і що нам потрібна безпека мережі , щоб зловити нас , якщо і коли ми робимо безлад!
Введіть тести.

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

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


7
@Tibos: Відключення тесту - це як коментування функції. У вас є контроль версій. Використай це.
Кевін

6
@Kevin Я не знаю, що ти маєш на увазі під «використовуй». Я відмічаю тест як "пропущений" або "очікуючий на розгляд" або будь-яку умову, яку використовує мій тестовий бігун, і виконую цей тег для контролю версій.
22:00

4
@dcorking: Я маю на увазі не коментувати код, видалити його. Якщо згодом ви вирішите, що вам це потрібно, відновіть його з контролю версій. Здійснення інвалідного тесту не відрізняється.
Кевін

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

6
@Tibos Прихильники тестування одиниць кажуть, що час циклу від написання невдалого тесту до написання коду має бути невеликим (наприклад, 20 хвилин. Деякі претендують на 30 секунд). Якщо у вас немає часу написати код негайно, це, мабуть, занадто складно. Якщо він не є складним, видаліть тест, оскільки його можна буде переписати, якщо скинута функція знову буде додана. Чому б не прокоментувати це? Ви не знаєте , що ця функція буде коли - або знову додала, так що закоментований тест (або код) , це просто шум.
CJ Dennis

32

Чому невдалі одиничні тести вважаються поганими?

Вони не є - тестова розробка будується на понятті провальних тестів. Невдалі тестові одиниці для керування розробкою, невдалі тести прийняття для керування історією ....

Те, що вам не вистачає, це контекст ; де дозволено невдачу одиничних тестів?

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

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

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

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

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

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

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

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

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

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


Я б сказав: "Немає нічого поганого в тому, що не вистачає тестів, які відключені ".
CJ Dennis

Ця зміна, безумовно, прояснює сенс. Дякую.
VoiceOfUnreason

26

Є багато чудових відповідей, але я хотів би додати ще один кут, який, на мою думку, ще недостатньо висвітлений: у чому саме полягає тест на тести.

Експериментальні тести не існують, щоб перевірити, чи не код ваш код.

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

Блок тестів перевіряє, що ваш код робить те, що ви думаєте, що робить.

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

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

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

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


2
Мені колись довелося замінити бібліотеку на іншу. Експериментальні тести допомогли мені переконатися, що всі кутові випадки все одно розглядаються новим кодом.
Thorbjørn Ravn Andersen

24

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

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

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

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

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


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

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

Ця відповідь чудова за власним досвідом. Як тільки деякі люди звикають ігнорувати купу провальних тестів або порушувати кращі практики в деяких моментах, нехай пройде пару місяців, і ви побачите, що% проігнорованих тестів різко зростає, якість коду падає до рівня "хак-скрипт" . І буде дуже важко згадати всіх про процес.
usr-local-ΕΨΗΕΛΩΝ

11

Ось основна логічна помилка:

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

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

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


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

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

9

Відповідь Філла W чудова. Я не можу його замінити.

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

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

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

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


Це може створити конфлікти щодо правил команди. Я фактично стикався з цим кілька тижнів тому:

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

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

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


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

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

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

1
Прапорські риси фіксують очевидний парадокс.
RubberDuck

1
@Flater так, і для переробки існуючої логіки.
RubberDuck

6

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

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

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

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


6

Щоб додати кілька балів до вже хороших відповідей ...

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

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

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

Інші відповіді охопили межі тестування.

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

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

Чому повинна бути дорожня карта?

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

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


6

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

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

public class MyProgram {
  public boolean alwaysTrue() {
    return true;
  }

  @Test
  public void testAlwaysTrue() {
    assert(alwaysTrue() == true);
  }
}

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

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

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

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

Це перешкоджає випробовуванню тестових модулів наперед - перед реалізацією.

Розробники будестримуйте написання будь-яких тестів, якщо вони не розуміють його перевагза своєю природою (якщо вони не походять з QA)


"Розробники стримуватимуть [писати] будь-які тести за своєю природою" - це абсолютно нісенітниця. Я працюю в цілій компанії розробників, які практикують TDD та BDD.
RubberDuck

@RubberDuck Я намагався відповісти на "факт", про який йдеться, і я перебільшував. Я
оновлю

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

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

@BenVoigt Я не думаю, що від мене очікується відповідь на "значну програму".
користувач7294900

4

Він просуває ідею, що код повинен бути ідеальним, а помилок не повинно існувати

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

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

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

  • Без тесту не вдалося, ви не знаєте, чи справді код перевіряється тестом. Це може бути взагалі не пов'язаним.
  • Змінивши код, щоб точно зробити тест перетворитись на червоний на зелений, нічого більше і нічого менше, ви можете бути впевнені, що ваш код робить те, що він повинен робити, і не набагато більше (що вам ніколи не знадобиться).

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

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

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

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

Це перешкоджає випробовуванню тестових модулів наперед - перед реалізацією.

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

Я чогось тут пропускаю? Чому організації очікують проходження всіх одиничних тестів?

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

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

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

Хіба це не життя у світі мрії?

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

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

Абсолютно ні, навіщо це?

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

Очевидно, що писати погані тести - це погано. Але це не має нічого спільного з функцією тестів як такої.


3

(З моїх оригінальних коментарів)

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

Як вправу, спробуйте замінити у запитанні фразу "unit test" на "помилка компілятора" (або "помилка синтаксису", якщо немає компілятора). Очевидно, що випуск не повинен мати помилок компілятора, оскільки це було б непридатним; але помилки компілятора і синтаксичні помилки - це звичайний стан справ на машині розробника, коли вони пишуть код. Помилки зникають лише після їх закінчення; і саме тоді слід натиснути код. Тепер замініть "помилку компілятора" в цьому пункті на "тест одиниці" :)


2

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

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

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

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

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

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

Це стримує випробування блоку запису наперед

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

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

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


2

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

в будь-який момент часу всі одиничні тести повинні пройти

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

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

Це також відповідає темі створення нових тестів: тести повинні затверджувати логіку та поведінку коду. Граничні умови, умови несправності тощо. Коли я пишу нові тести, я намагаюся ідентифікувати ці «гарячі точки» в коді.

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

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


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

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

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

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

UPDATE my_table(
SET column_1 = 'MyValue'
WHERE id_column = 123;

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

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

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


0

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

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

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


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

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

0

"але в будь-який момент часу всі одиничні тести повинні пройти"

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

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

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

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

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


-7

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

Один відомий приклад цього відбувається в грі 2,4,6.

  • У мене в голові правило, що будь-яка серія з трьох чисел пройде або провалиться,
  • 2,4,6 - пропуск
  • Ви можете перерахувати набори з трьох чисел, і я скажу вам, чи проходять вони, чи не вдаються.

Більшість людей обирають правило, кажуть, що "проміжок між 1-м і 2-м номером такий же, як проміжок між 2-м і 3-м".

Вони перевірять деякі цифри:

  • 4, 8, 12? Перехід
  • 20, 40, 60? Перехід
  • 2, 1004, 2006? Перехід

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

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

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

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


2
Наскільки це стосується питання? Невдалі одиничні тести є свідченням проблеми за визначенням.
Фракс

1
Ви абсолютно можете провести одиничні тести, які вимагають, щоб тестувана система перейшла в режим відмови. Це не те саме, що ніколи не бачити тест невдало. Ось чому TDD визначається як цикл "Червоний -> Зелений -> Рефактор"
Кале
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.