Подтвердить что ты не робот

Можно ли копировать и вставлять модульные тесты, когда логика в основном одинакова?

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

Это слишком плохо, если я просто скопирую 10 тестов, которые у меня уже есть для левого движения, и сделаю только необходимые изменения и сделаю то же самое для самого кода? Или я должен идти снова и делать каждый тест с самого начала, даже если логика в основном одинакова?

4b9b3361

Ответ 1

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

Суть заключается в том, что дублирующий код почти всегда является неправильным. В этом примере вы можете реорганизовать проверяющий код в метод, называемый, например IsTetrisPieceUnableToMoveLeftBecauseOfAPieceOrAWall. Я всегда использую очень описательные имена методов, например, при написании "общих" функциональных возможностей для unit test, поскольку это делает его чрезвычайно понятным только, что делается/проверено.

Ответ 2

У меня есть несколько спорная позиция по этому вопросу. Хотя в производственном коде следует избегать дублирования кода, это не так уж плохо для тестового кода. Производственный и тестовый код отличаются по своей природе и намерениям:

  • Производственный код может позволить себе некоторую сложность, чтобы быть понятным/поддерживаемым. Вы хотите, чтобы код находился на правильном уровне абстракции, а дизайн был последовательным. Это нормально, потому что у вас есть тесты для этого, и вы можете убедиться, что он работает. Дублирование кода в производственном коде не было бы проблемой, если бы у вас действительно было 100% -ное покрытие кода на логическом уровне. Этого действительно трудно достичь, поэтому правило: избегать дублирования и максимизировать охват кода.

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

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

PS: Если вы действительно не согласны, пожалуйста, оставьте комментарий.

Ответ 3

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

Это означает, что если у вас есть общая логика, извлеките ее в свою собственную функцию.

Некоторые библиотеки unit test, такие как семейство xUnit, имеют специальные атрибуты тестирования, настройки и разрыва для такого общего кода.

См. этот, связанный с этим вопрос: "Почему копия кода опасна?".

Ответ 4

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

Однако это только шаг 1. Шаг 2 - это рефакторинг для общности, а шаг 1 - только для того, чтобы помочь вам увидеть эту общность. Если вы уже можете видеть это ясно, не копируя (иногда проще сначала скопировать, а затем проверить, иногда это не так, и это зависит от того, кто это делает), а затем пропустите шаг 1.

Ответ 5

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

Ответ 6

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

Ответ 7

На веб-сайте xunitpatterns.org говорится: "Нет" (копирование/вставка не работает), потому что это может увеличить затраты, когда тесты необходимо обновить:

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

и для дальнейшего чтения он также ссылается на статью

По: Ари ван Дюрсен, Леон Лунен, Алекс ван ден Берг, Джерард Кок

Ответ 8

Я согласился @Rob. Код нуждается в рефакторинге. Но если вы не хотите делать рефакторинг кода в этот момент времени, вы можете пойти и выполнить параметризованные тесты. Тот же тест для разных параметров. См. TestCase и TestCaseSource атрибуты в nunit.

См http://nunit.org/index.php?p=parameterizedTests&r=2.5