Скопійований і вставлений тестовий код: Наскільки це погано?


12

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

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

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

EDIT: Інструмент, який я використовую, - SilkTest, який є власною мовою під назвою 4Test. Крім того, ці тести здебільшого використовуються для настільних додатків Windows, але я також перевіряв веб-додатки, використовуючи цю налаштування.


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

Також, що це за мова? У вас може бути щось доступне, що просто не виникає на увазі, що дозволить повторно використовувати (як-от функції першого класу). З іншого боку, випадки випробування які повинні бути простими, щоб тримати це менш імовірно , що вони мають помилки самі по собі ...
Izkata

3
У всьому, що я написав, тестовий код не виключається з рефакторингу.
Саймон Уайтхед,

Відповіді:


23

Скопійовані та відредаговані тестові справи часто копіюються.

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

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


1
В основному це я відчуваю. Майже однаковий тестовий код нормальний у багатьох випадках, але повторюваний однаковий тестовий код - це погана новина.
joshin4colours

12

Повторення - корінь усього зла

Це правильно! Повторення - корінь усього зла . Ймовірно, це говорив Кнут у своїй книзі «Передчасна оптимізація - корінь усього зла», але я думаю, що це повторення.

Щоразу, коли ви дивитесь програму чи пишете її, і виявляєте якесь повторення: видаліть її! Вбийте його негайно… що завгодно, але позбудьтесь цього !

Кожен раз, коли я вводив якесь повторення і мусив виправити помилку, я забував виправити репліку ... (Дональд Кнут). Отже, коли є повторення, просто видаліть його як можна краще, не зламайте !

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

Ось гарне прочитання з Code Horror, яке мене надихає - Скромна пропозиція щодо повторного використання школи копіювання та вставки .


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

так, я взяв станції з Кнут :)
Юсубов

9
Ви повторили себе: Ви повторили себе, сказавши «Повторення - корінь усього зла» у заголовку та вашому вступному реченні.
Томас Едінг

Так, я це робив навмисно, щоб наголосити на важливості, і ви можете редагувати цю частину :)
Юсубов,

1
Томасе Едінг, ти також повторив себе. Ви також повторили себе =)
marktani

7

Це все ще досить погано вирізати та наклеїти. Є кілька проблем.

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

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

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

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


> виклик до помічника методу з описовим іменем. Хіба не проблема в тому, що ваші одиничні тести тепер перетворюються на програми самі по собі - чого слід уникати. Що робити, якщо деякі тести виявляються невідповідними - це порушений код або помічники тесту?
dwjohnston

4

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

Для тестування GUI, ви можете подивитися шаблон PageObject, щоб зменшити повторний код.


2

Я рекомендую підібрати XUnit візерунки. У мене була та сама проблема, поки я не почав використовувати цю книгу. У Object Mother звуки картини , як це було б найбільш корисним для вашого сценарію.

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


+1 для Object Mother patternзагального коду ініціалізації.
k3b

2

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

Я хотів би запитати декілька речей: 1) Наскільки ймовірно, що ця функціональність, що тестується в UAT, зміниться? Якщо це навряд чи це зміниться, то є менше шансів, що вам доведеться оновлювати кожен свій набір коду. 2) Якщо в UAT є зміна, чи завжди вона впливатиме на кожен набір скопійованого коду чи може вплинути лише на один чи два набори? Якщо він може бути ізольованим і вимагати зміни лише одного набору, це може допомогти розділити речі. 3) Наскільки складним буде початковий метод, якщо ви спробуєте і впораєтеся з ним усіма сценаріями? Ви додаєте багато вкладених if / else / циклів? Якщо ви почнете надмірно виконувати всі розгалуження, можливо, у вас виявиться код, який важко зрозуміти. Чи було б легше зробити оновлення в кожному скопійованому тексті, ніж було б переглянути всю логіку розгалуження?

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


0

Одна велика процедура

Одна думка: Це здається, що ви намагаєтесь уникнути вирізаного коду, зробивши такі методи:

testScreen(title, fieldList, linkList, param1, param2, param3,...) {
    test that the layout at the top of the screen is correct
    test if PageTitle == title?
    for each field in fieldList:
        check that it appears in order on the screen
    for each field in linkList:
        check that it appears in order on the screen
    test if param1 is whatever...
    test if param2 is whatever...
    etc.
    test that the bottom of the screen is correct
}

Багато маленьких процедур (інструментарій)

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

testScreenTop()
verifyLinks(list)
testScreenBottom()

Ви все одно вирізаєте та вставляєте ці процедури на кожен екран, але ви вирізаєте та вставляєте менші шматки коду та вирізаєте шматки спільності, які не вирізати та вставляти (вміст кожної невеликої кількості процедур).

Вирізати і вставити

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

Автоматизоване тестування на інтерфейс користувача

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


0

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


0

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

Уявіть такий сценарій помилок:

  • Хтось вносить зміни до бази даних, від якої залежить багато вашого тесту.
  • Наслідок: раптом 117 із 2933 автоматизованих тестів вийшли з ладу.

Що ти робитимеш?

  • (1) виправити 117 тестів?
  • (2) видалити 117 тестів і повторно доповнити їх новою копією та вставкою. це може бути простіше, ніж (1)
  • (3) перефактуруйте тести, щоб отримати загальний код, щоб у майбутньому вам довелося адаптувати лише один метод (або кілька) для виправлення тестів (див. Відповіді @pdr або @Michael Brown)
  • (4) видалити 117 тестів без повторного доповнення тестів

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

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

Після деяких сценаріїв "сценарії помилок" управління віддає перевагу (4), оскільки виправити "копіювати та вставити тести" так дорого.

Зробити це правильно в першу чергу (3) буде не так швидко, але збільшить шанси на те, що тести виживуть

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