Поблочное тестирование.NET - Лучшие практики для сокрытия тестовых швов в коде выпуска

Вот оптимальный код, который объединяет два других ответа:

git for-each-ref --sort=-committerdate refs/heads/ --format='%(committerdate:short) %(authorname) %(refname:short)'
5
задан STW 16 July 2009 в 18:54
поделиться

11 ответов

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

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

Однако, чтобы ответить на ваши актуальные вопросы:

  • Да, имеет смысл запускать модульные тесты против неотладочных сборки - это дает больше уверенности в том, что изменения между отладочной и неотладочной сборками ничего не сломают.
  • Да, вы можете использовать свой собственный символ препроцессора (например, TEST), если хотите; вы можете применить это в существующих конфигурациях или создать новую конфигурацию сборки.
3
ответ дан 18 December 2019 в 07:10
поделиться

Мы обязательно запускаем тесты против сборок Release / Obfuscated, потому что мы часто обнаруживаем проблемы таким образом, так что да, я думаю, что есть смысл заставить их работать.

Obfuscation делает внутренние компоненты полностью непригодными для использования, что для меня достаточно , поэтому мы оставляем методы тестирования (и делаем их внутренними). ​​

В целом, я бы предпочел, чтобы код был протестирован, чем беспокоился о том, что они там есть - если они не влияют на производительность.

3
ответ дан 18 December 2019 в 07:10
поделиться

На самом деле вы находитесь на пути к внедрению зависимостей - вы просто еще этого не осознали :)

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

Я писал об этом не так давно в Тестируемость - это действительно открытый / закрытый принцип .

В вашем конкретном случае, в класс MethodLogger следует внести несколько изменений:

  1. Сделать его классом экземпляра вместо статического класса. Как скажут вам все опытные специалисты по TDD, статика - это зло .
  2. Пусть только конструктор принимает экземпляр IMethodLogger. Это называется Constructor Injection и заставляет всех клиентов принимать явное решение о том, как вести журнал.
  3. Либо настройте график зависимостей вручную, либо используйте контейнер DI, чтобы связать MethodLogger с желаемым IMethodLogger .
3
ответ дан 18 December 2019 в 07:10
поделиться

Наличие #IF DEBUG и т. Д. - плохой тон.

Рабочий код не должен зависеть от кода тестирования / отладки.

Я бы посоветовал изучить внедрение зависимостей, чтобы помочь в модульном тестировании.

2
ответ дан 18 December 2019 в 07:10
поделиться

Согласно книге Майкла Фезерса «Эффективная работа с устаревшим кодом», кажется, было бы лучше, если бы вы назвали сеттер чем-то особенным для тестирования.

Пример: SetTestingLogger (регистратор IMethodLogger)

Я бы также удалил операторы препроцессора. В книге также говорится, и я цитирую

: «Вас может немного подташнить идея, что вы удаляете доступ защита при использовании статического сеттера, но помните, что цель защита доступа предназначена для предотвращения ошибки. Мы проводим испытания также предотвращать ошибки ».

Заключение: Казалось бы, было бы лучше разместить эти хуки, потому что вы размещаете их с целью тестирования и, в конечном итоге, для удаления ошибок.

Раздел «Введение в статический сеттер» в книге объясняет это более подробно. Я бы порекомендовал ее как книгу, которую должен иметь каждый разработчик.

2
ответ дан 18 December 2019 в 07:10
поделиться

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

1
ответ дан 18 December 2019 в 07:10
поделиться

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

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

IMO лучший способ выполнить то, что вы пытаетесь выполнить с помощью SetLogWriter, - это фактически использовать инверсию контейнера управления, например StructureMap , чтобы назначить конкретные объекты в время выполнения на основе различных конфигураций. Во время модульного тестирования вы можете использовать такую ​​библиотеку, как Moq , для производства бетонов, которые ведут себя ожидаемым образом (SQL-запрос, который всегда возвращает один и тот же точный результат), хотя в вашем конкретном случае вы выполняете прямо противоположное ( желаемое ведение журнала во время модульных тестов по сравнению с отсутствием ведения журнала во время производственного цикла).

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

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

1
ответ дан 18 December 2019 в 07:10
поделиться

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

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

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

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

Ну, я больше комментировал общие принципы организации кода. Как правило, создание таких хуков для вашего кода - хорошая идея; в вашем случае вы не будете «повышать разрешения, чтобы избавиться от хлопот», вы бы «разрабатывали надежную и гибкую структуру ведения журнала».

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

Как правило, создание таких ловушек для вашего кода - хорошая идея; в вашем случае вы не будете «повышать права доступа для устранения проблем», вы будете «проектировать надежную и гибкую структуру ведения журнала».

1
ответ дан 18 December 2019 в 07:10
поделиться

Вы можете использовать Typemock Isolator, чтобы обойти любые проблемы проектирования, которые ухудшают тестируемость. в отличие от других фреймворков, он также будет работать со статическими методами, частными методами и не виртуальными методами. когда вы научитесь лучше разрабатывать, ваш код по умолчанию будет более "тестируемым", но если вы хотите просто обойти эти проблемы сейчас, это поможет

http://blog.typemock.com/2009/01/isolator-new-vbnet-friendly-api.html

(также единственный инструмент с дружественным к VB API)

4
ответ дан 18 December 2019 в 07:10
поделиться

Могу ли я использовать настраиваемый флаг предварительного компилятора, например "ТЕСТ" вместо "DEBUG"? Как бы я пошел о том, чтобы сообщить Visual Studio всегда перестроить цель с этим флагом для тестирование, чтобы убедиться, что мои крючки / швы есть в наличии?

Да. Что вы хотите сделать, так это добавить символ условной компиляции. Вы можете сделать это в свойствах проекта на вкладке «Сборка». Вы можете создать другую конфигурацию сборки в Configuration Manager и добавить в новую конфигурацию только символ TEST.

0
ответ дан 18 December 2019 в 07:10
поделиться
  1. как говорили другие, двигаться к внедрению зависимостей и инверсии управления (IoC)
  2. хорошо изолировать тестируемые классы с помощью структур изоляции (Moq и т. Д.) )
  3. переносить тесты в отдельную сборку - нет необходимости в #if DEBUG ... #endif
2
ответ дан 18 December 2019 в 07:10
поделиться