Скопируйте и вставьте тестовый код: насколько это плохо?


12

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

Вместо этого я обычно копирую большой кусок тестового кода из одного раздела, вставляю его в другой и делаю любые небольшие изменения, которые мне нужны. Я не использую более структурированные способы кодирования, такие как использование большего количества ОО-принципов или функций.

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

РЕДАКТИРОВАТЬ: инструмент, который я использую, SilkTest, который на проприетарном языке называется 4Test. Кроме того, эти тесты в основном предназначены для настольных приложений Windows, но я также тестировал веб-приложения, используя эту настройку.


Какой тестовый инструмент вы используете? Возможно, ваша среда тестирования не поддерживает типы тестов, которые вы пишете. Сокращение-вставка более чем трех строк, как правило, очень плохо, но если вы можете явно добавить больше долгосрочной ценности, автоматизируя тест GUI, чем каждый раз, когда вы выполняете его вручную, то все, что вы делаете, вероятно, чертовски дорого. хороший.
ГленПетерсон

Кроме того, что это за язык? У вас может быть что-то доступное, что просто не вспомнить, что позволит использовать повторно (например, функции первого класса). С другой стороны, случаи испытания которые должны быть простыми, чтобы держать это менее вероятно , что они имеют ошибки сами по себе ...
Izkata

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

Ответы:


23

Скопированные и затем отредактированные тестовые примеры часто бывают хороши.

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

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


1
Это в основном то, что я чувствую. Практически идентичный тестовый код в большинстве случаев подходит, но повторение идентичного тестового кода - плохая новость.
joshin4colours

12

Повторение - корень всего зла

Это верно! Повторение является корнем всего зла . Возможно, Кнут говорил в своей книге «Преждевременная оптимизация - корень всего зла», но я думаю, что это повторение.

Всякий раз, когда вы смотрите на программу или пишете ее, вы обнаруживаете какое-то повторение: удалите ее! Убей это немедленно ... что угодно, но избавься от этого !

Каждый раз, когда я вводил какое-то повторение и должен был исправить ошибку, я забывал исправить реплику ... (Дональд Кнут) Поэтому, когда есть повторение, просто удалите его как можно лучше, не взламывайте !

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

Вот хорошее чтение из Code Horror, которое вдохновляет меня - скромное предложение для школы повторного использования кода .


«Каждый раз, когда я вводил какое-то повторение и должен был исправить ошибку, я забыл исправить реплику…». Кроме того, если вы нажали c & p и забыли настроить скопированный текст в соответствии с текущим контекстом, это сильно повредит. Исправленный тестовый код не похож на оптимальную ситуацию, не так ли?
Марктани

да, я взял станции от Кнута :)
Юсубов

9
Вы повторили: вы повторили, сказав «Повторение - корень всего зла» в заголовке и вашем вступительном предложении.
Томас Эдинг

Да, я сделал это намеренно, чтобы подчеркнуть важность, и вы можете редактировать это часть :)
Юсубов

1
Томас Эдинг, ты тоже повторил. Вы тоже повторились =)
Марктани

7

Это все еще довольно плохо вырезать и вставлять. Есть несколько проблем.

Ваши тесты могут быть хрупкими, потому что вы уязвимы для чего-то, что требует изменения во всем этом коде, скопированном и вставленном. Придется ли вам переписывать все тесты?

Если вы не можете инкапсулировать логику в вспомогательные методы вне ваших тестов, вы не можете написать тесты самих этих вспомогательных методов. Написание тестов тестовых методов обычно сложно сделать стоящим, так как вы должны сломать свой код, чтобы протестировать тест. Но вы можете тестировать вспомогательные методы.

Это может сделать тесты менее читабельными. Большой блок скопированного кода может быть сложнее для чтения, чем вызов вспомогательного метода с описательным именем.

Все, что я перечислил, может быть проблемой. Если вы обнаружите, что ни один из них на самом деле не является проблемой, тогда, конечно, все в порядке.


> вызов вспомогательного метода с описательным именем. Не проблема ли это в том, что ваши юнит-тесты теперь становятся программами сами по себе - чего следует избегать. Что, если некоторые тесты дают сбой - это код, который сломан, или помощники теста?
dwjohnston

4

Я имел обыкновение соглашаться с вами. Но затем со временем я обнаружил, что каждое внесенное мной изменение (в частности, изменения DI в модульных тестах) требовало многочисленных изменений, и это было громоздко. Теперь я подписываюсь на школу DRY, даже когда пишу тесты.

Для тестирования графического интерфейса вы можете посмотреть на шаблон PageObject, чтобы уменьшить количество повторяющихся кодов.


2

Я бы порекомендовал подобрать шаблоны XUnit. Раньше у меня была точно такая же проблема, пока я не начал использовать эту книгу. В Object Mother звуки картины , как это было бы наиболее полезным для вашего сценария.

Как и кто-то еще упомянул, правильная инкапсуляция этого установочного кода может быть обременительной, но необходимость менять его во всех местах, которые вы копируете и вставляете, еще более важна.


+1 за Object Mother patternобщий код инициализации.
k3b

2

Должны ли люди пытаться ограничить повторение, когда они могут - да. Но выигрыш зависит от ситуации. Это может вернуться к дискуссии о «лучшей практике». Но вопрос в том, что лучше для вас в этой ситуации. Есть исключения из каждого правила.

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

Если вы застряли copy / paste / alter, я думаю, вы захотите добавить комментарии, такие как «Это скопировано в методе 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 строк, я бы действительно решил что-то с этим сделать. По крайней мере, предпримите шаги, чтобы минимизировать это!

Автоматизированное тестирование пользовательского интерфейса

Черт возьми, если вы можете доказать большую производительность с помощью автоматического тестирования пользовательского интерфейса, чем ручное тестирование с использованием любого метода (стоимость написания / поддержки автоматических тестов ниже, чем тестирование вручную каждый раз, но качество такое же), я думаю, вам следует написать статью. Я бы прочитал это! Теперь я вижу заголовок «Вырежьте и вставьте код в Net Win для тестирования пользовательского интерфейса!»


0

Это действительно не так уж и плохо. На самом деле, если вы обнаружите, что определенные шаблоны кода используются очень часто, а изменения являются очень рутинными (например, несколько строк или значений параметров), вы можете даже написать генератор кода, который генерирует повторяющийся тестовый код на основе небольшого числа (- иш?) введите список значений, которые меняются. Я сделал это (сгенерированный тестовый код) много раз, используя пакетные файлы, сценарии SQLPlus, даже макросы Excel (это звучит некрасиво, но переменные для различных тестовых сценариев уже были в электронной таблице), и это может сэкономить время , Дело в том, что если что-то изменится в общей структуре повторяющегося кода тестового примера, вы можете просто восстановить все, что вам нужно.


0

Это то же самое, что и большинство других ответов, но не так, как технический менеджер.

Представьте себе следующий сценарий ошибки:

  • Кто-то вносит изменения в базу данных, от которой зависит множество ваших тестов.
  • Следствие: внезапно 117 из ваших 2933 автоматических тестов не пройдены.

Что ты будешь делать?

  • (1) исправить 117 тестов?
  • (2) удалите 117 тестов и переопределите их с помощью нового копирования и вставки. это может быть проще, чем (1)
  • (3) реорганизовать тесты для извлечения общего кода, чтобы в будущем вам пришлось адаптировать только один метод (или несколько) для исправления тестов (см. Ответы @pdr или @Michael Brown)
  • (4) удалить 117 тестов без переопределения тестов

Из моего опыта:

При внедрении автоматизированного управления тестами нравится «копировать и вставлять тесты»: вы получаете множество тестов за короткое время.

После некоторых «сценариев ошибок» руководство предпочитает (4), потому что исправление «copy & paste-tests» стоит очень дорого.

Сделайте это правильно, во-первых (3) не будет так быстро, но увеличивает шансы на выживание тестов

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.