Вопреки другим ответам, важно отметить, что некоторые способы тестирования могут стать хрупкими при реорганизации тестируемой системы (SUT), если тест представляет собой whitebox.
Если я использую фреймворк, который проверяет порядок методов, вызываемых на макетах (когда порядок не имеет значения, поскольку вызовы не имеют побочных эффектов); тогда, если мой код будет чище с этими вызовами методов в другом порядке, и я проведу рефакторинг, мой тест будет прерван. В общем, макеты могут вносить хрупкость в тесты.
Если я проверяю внутреннее состояние моего SUT, выставляя его закрытых или защищенных членов (мы можем использовать «друг» в Visual Basic или повысить уровень доступа «внутренний» и использовать «internalsvisibleto» в c #; во многих языках ОО, включая c # можно использовать « подкласс специфичного для теста »), тогда внезапно будет иметь значение внутреннее состояние класса - возможно, вы реорганизуете класс как черный ящик, но тесты белого ящика не пройдут. Предположим, что одно поле повторно используется для обозначения разных вещей (не очень хорошая практика!), Когда SUT изменяет состояние - если мы разделим его на два поля, нам может потребоваться переписать неработающие тесты.
Специфичные для теста подклассы также могут использоваться для тестирования защищенных методов - это может означать, что рефакторинг с точки зрения производственного кода является принципиальным изменением с точки зрения тестового кода. Перемещение нескольких строк в защищенный метод или из него может не иметь побочных эффектов производства, но может нарушить тест.
Если я использую « тестовые зацепки » или любой другой специфичный для теста или условный код компиляции, может быть трудно гарантировать, что тесты не сломаются из-за хрупких зависимостей от внутренней логики.
Таким образом, чтобы предотвратить привязку тестов к внутренним деталям SUT, это может помочь:
- Используйте заглушки, а не издевательства, где это возможно. Для получения дополнительной информации см. Блог Фабио Периера о тавтологических тестах и мой блог о тавтологических тестах .
- При использовании макетов избегайте проверки порядка вызываемых методов, если это не важно.
- Старайтесь избегать проверки внутреннего состояния вашей SUT - используйте его внешний API, если это возможно.
- Старайтесь избегать специфичной для теста логики в производственном коде
- Старайтесь избегать использования тестовых подклассов.
Все вышеперечисленные пункты являются примерами соединения белого ящика, используемого в тестах. Поэтому, чтобы полностью избежать рефакторинга тестов на взлом, используйте тестирование SUT в «черном ящике».
Отказ от ответственности: Чтобы обсудить рефакторинг здесь, я использую слово более широко, чтобы включить изменение внутренней реализации без каких-либо видимых внешних эффектов. Некоторые пуристы могут не соглашаться и ссылаться исключительно на книгу Мартина Фаулера и Кента Бека «Рефакторинг», в которой описываются операции атомного рефакторинга.
На практике мы склонны предпринимать несколько большие неразрывные шаги, чем описанные там атомарные операции, и, в частности, изменения, из-за которых производственный код ведет себя идентично извне, могут не оставить прохождение тестов. Но я думаю, что было бы справедливо включить «алгоритм замены для другого алгоритма, который имеет идентичное поведение» в качестве рефакторинга, и я думаю, что Фаулер с этим согласен. Сам Мартин Фаулер говорит, что рефакторинг может нарушить тесты:
Когда вы пишете пробный тест, вы проверяете исходящие вызовы SUT, чтобы убедиться, что он правильно общается со своими поставщиками. Классический тест заботится только о конечном состоянии, а не о том, как это состояние было получено. Тесты Mockist, таким образом, более связаны с реализацией метода. Изменение характера обращений к сотрудникам обычно приводит к срыву теста mockist.
[...]
Связь с реализацией также мешает рефакторингу, так как изменения реализации гораздо чаще нарушают тесты, чем при классическом тестировании.
Фаулер - издевательства не окурки