Як покращити тестування власного коду


45

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

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

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


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

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

6
@Brian, я думаю, ви повинні скористатися ними незалежно від того, чи користуються ними інші. Можливо, показ гарної практики змусить наслідувати інших.
CaffGeek

Відповіді:


20

Завдання кодера - будувати речі.

Завдання тестера - зламати речі.

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


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

8
@Matthew Rodatus - Обсяг тестування на стороні кодера спрямований лише на те, щоб перевірити, що працює. З боку тестера, мета - знайти помилки, а не спостерігати за тим, що код працює.
mouviciel

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

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

2
@Dave Lasley - Це якраз моя думка: архітектор - не найкраща людина, щоб зруйнувати свій будинок: він занадто пишається тим, наскільки сильним він може бачити його дефекти. Тільки інший архітектор (а не хлопець з вулиці) може привести об'єктивний погляд на будинок і виявити, що будинок може зламатися за певних умов, які колишній архітектор був занадто сліпим, щоб уявити.
mouviciel

14

Франциско, я зроблю тут деякі припущення, виходячи з того, що ви сказали:

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

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

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

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

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


11

Якщо ви кодуєте в C, Objective-C або C ++, ви можете використовувати CLang Static Analyzer, щоб критикувати джерело, не використовуючи його.

Доступні деякі засоби налагодження пам’яті: ValGrind, Guard Malloc на Mac OS X, Electric Fence на * NIX.

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

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

Використовуйте твердження - макрос assert () в C, C ++ та Objective-C. Якщо ваша мова не забезпечує функції затвердження, напишіть її самостійно.

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

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

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

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

(Чомусь я ніколи не був прихильним, хоча BeOS міг працювати без файлу swap, це було вкрай нестабільно. Домінік Гіампаоло, який написав файлову систему BFS, закликав мене ніколи не запускати BeOS без заміни. Я не дивіться, чому це має значення, але це, мабуть, був якийсь артефакт впровадження.)

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

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

Спробуйте вбити свій додаток за допомогою налагоджувача або з "kill -9" на * NIX, поки він прямо в середині запису великого важливого файлу. Якщо ваша програма добре архітектурована, весь файл буде написаний або взагалі не буде записаний, або, можливо, якщо він буде написаний лише частково, те, що буде написано, не буде пошкоджено, а дані, що зберігаються, повністю використовуються додаток після повторного читання файлу.

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


1
+1 багато практичних порад, яким не потрібна підтримка з боку інших. Єдине, що я хотів би додати, це те, що аргумент призначений для документування та перевірки умов, які не можуть бути збійними, якщо в коді немає помилки . Ніколи не стверджуйте про речі, які можуть вийти з ладу через «невдачу», наприклад, не знайдені важливі файли або недійсний вклад тощо.
Іван Голдбі

10

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

  1. Як я розбиваю цю "штучку" на шматки, які можна перевірити? Як я можу виділити лише те, що хочу перевірити? Які заглушки / макети я повинен створити?
  2. Для кожного фрагмента: Як перевірити цю частину, щоб переконатися, що вона правильно відповідає на розумний набір правильних даних?
  3. Для кожного фрагменту: Як перевірити, чи фрагмент відповідає правильно на неправильні введення (покажчики NULL, недійсні значення)?
  4. Як перевірити межі (наприклад, де значення переходять від підписаних до непідписаних, 8-бітових до 16-ти бітових тощо)?
  5. Наскільки добре мої тести покривають код? Чи є якісь умови, які я пропустив? [Це чудове місце для інструментів покриття коду.] Якщо є код, який був пропущений і його ніколи не можна виконати, чи дійсно це потрібно бути там? [Це зовсім інше питання!]

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

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


5

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

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


1
+1 для цикломатичної складності. "Мені важко дотримуватися всіх можливих шляхів, щоб я міг знайти помилок", для мене означає, що код ОП може знадобитися розбити на менші, менш складні шматки.
Toby

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

3

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

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


3

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

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

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


1
+1 для згадування бачення речей з точки зору користувача.
Матвій Родатус

3

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

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

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

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


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

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


2

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

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


2

Тестування чорної коробки! Ви повинні створювати свої класи / методи з урахуванням тестування. Ваші тести повинні базуватися на специфікації програмного забезпечення та повинні бути чітко визначені на вашій послідовності діаграми (за допомогою випадків використання).

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

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

Але вам справді слід робити якесь автоматизоване тестування; цей матеріал рятує життя.


2

З мого досвіду

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

UML - це інший витратний час. одна дошка + ручка могла б зробити те саме, дешевше і швидко.

До речі, як бути хорошим у кодуванні (і уникати помилок)?

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

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

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

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

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

  • f) додайте коментарі до свого коду.

  • g) введення користувача як джерело помилок. визначте його. Наприклад, інжекція SQL викликається введенням користувача.

  • h) Визначте поганий елемент команди та відокремте поставлене завдання. Деякі програмісти схильні вкручувати код.

  • i) Уникайте зайвого коду. Якщо, наприклад, класу потрібен інтерфейс, то використовуйте його, інакше не уникайте додавання неактуального коду.

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

  • кнопка працює? ... так.
  • база даних щось зберігає ?. ні, тому помилка була в середньому кроці.
  • потім працює клас, який зберігається в базі даних ?. ні <- добре, я знайшов помилку. (це було пов'язано з дозволом бази даних). Тоді я перевірив не тільки цю процедуру, але й кожну процедуру, яка робить те саме (бо гомологія коду). На відстеження помилки у мене знадобилося 5 хвилин і 1 хвилина на її вирішення (та багато інших помилок).

І стороною

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


2

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

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

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

  1. Налагодження ; встановити точки коду в коді та запустити програму. Як тільки ви потрапили на точку розриву, переходьте по лініях під час взаємодії з програмою.
  2. Автоматизоване тестування ; написати код, який перевіряє ваш код. Це допомагає лише на рівнях нижче інтерфейсу користувача.
  3. Знайомтесь зі своїми тестерами ; вони можуть знати програму краще, ніж ви, тому навчайтеся у них. Запитайте їх, які слабкі сторони вашої програми та які тактики вони використовують для пошуку помилок.
  4. Знайомтесь зі своїми користувачами ; навчитися ходити у взутті своїх користувачів. Функціональні вимоги - це відбитки пальців ваших користувачів. Ваші користувачі часто знають про програму, яка, можливо, чітко не відповідає функціональним вимогам. Як ви краще зрозумієте своїх користувачів - характер їх роботи в реальному світі та те, як ваша програма повинна допомогти їм - ви краще зрозумієте, якою має бути програма.

2

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

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

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

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