Написання тестів на код, призначення якого я не розумію


59

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

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

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

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

Чи тут краща атака?


28
Я відчуваю, що ви почали неправильно. Спершу слід зрозуміти код, потім протестувати його, потім рефактор. Чому ви рефакторинг, не знаючи, для чого код?
Яків Райхле

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

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

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

3
Ви не можете запитати / переглядати його хтось, хто це розуміє?
pjc50

Відповіді:


122

У вас все добре!

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

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

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

  1. зрозуміти код "ззовні",
  2. написати регресійні тести,
  3. рефактор, що призводить до кращого розуміння внутрішніх кодів коду

21
Ідеальна відповідь, також точно так, як описано у книзі "Робота зі спадковим кодексом"
Алтойр,

Я повинен був зробити щось подібне колись. Зберіть типові вихідні дані з програми перед тим, як я змінив її, а потім перевірте нову версію програми, запустивши через неї ті самі тестові дані. 30 років тому ... Fortran ... Це була якась обробка зображень / картографування, тому я не міг реально знати, яким повинен бути вихід ", дивлячись на нього чи пишучи тестові приклади. І я зробив це на векторному (стійкому) дисплеї Tektronix. Робота уряду ... 2 Телетипи, що стукають за мною.

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

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

2
@nocomprende, Смішно, що я зробив саме цю справу зі спадковим науковим кодом fortran 77 минулого тижня. Додайте друк даних ascii до файлу, налаштуйте тестові каталоги з входами та очікуваним результатом, і мій тестовий випадок був просто різницею двох наборів виводу. Якщо вони не відповідають характеру за характером, я щось зламав. Коли в коді є переважно дві підпрограми, які є кожні 2-3k LoC, вам потрібно десь почати.
Годрік Провид

1

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

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

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


1
Будь-яка інформація краще, ніж сліпа. Я використовував для пошуку помилок у серверних програмах, які були у виробництві, викликаючи налагоджувач у файлі дампа збиття (Unix) і запитуючи трасування стека. Це дало мені назву функції, де сталася несправність. Навіть не маючи інших знань (я не знав, як використовувати цей налагоджувач), це допомогло в тому, що інакше було б загадковою та невідтворюваною ситуацією.
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.