Автоматический анализ покрытия кода с использованием OpenCover + плюшки

в 12:16, , рубрики: .net, unittest, тестирование, метки:

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

Уже сложно найти проект, в котором отсутствуют юнит-тесты. Их использование многим кажется избыточным, ведь это трата времени, которое с тем же успехом можно потратить на написание другого кода и “не, ну я точно знаю, что там все правильно”. Но, как мы убеждаемся, в долгосрочной перспективе тесты экономят больше времени, чем отнимают. Облегчается сопровождение кода, рефакторинг становится безопасным, отслеживается правильность любых изменений. Причем, чем выше покрытие — тем сильнее чувствуется полезность тестов.

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

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

Итак, чтобы начать пользоваться OpenCover, достаточно скачать исходники и собрать, используя Visual Studio. OpenCover являет собой консольное приложение, все необходимые опции задаются параметрами командной строки, так что прикрутить к любому сборщику, будь то MsBuild, Nant, Rake или что либо другое, не проблема.

Интересен механизм работы — OpenCover запускается вместе с прогоном юнит-тестов. Если быть точным, команда на запуск тестов передается ему в качестве нескольких параметров.(Если в аргументе есть пробелы, то он берется в кавычки полностью, например “-target:%application%”):

  • -target:%application% — приложение, которое нужно запустить (В нашем случае — Gallio.Echo, как более распространенный пример — nunit-console). Важное замечание — путь к приложению должен быть абсолютным, так как мы передаем его в качестве параметра, и в переменной Path он искаться не будет.
  • -targetdir:%path% — папка, в которой нужно запустить %application%
  • -targetargs:%args% — параметры, передаваемые %application%

Кроме того, у OpenCover есть еще аргументы, регулирующие непосредственно его работу. Приведу только те, которые использую сам, остальные можно найти тут

  • -output:%path% — указывает, куда поместить отчет
  • -filter:%filters% — Определяет, что учитывать при анализе. Фильтры имеют формат +[%assembly%]%type% для включаемых сборок/типов и то же самое, но со знаком минус в начале для исключаемых. Фильтров может быть множество, разделяются пробелами, в таком случае аргумент заключается в кавычки. Исключающие фильтры имеют приоритет над включающими.
  • -register — Динамическая регистрация сборки OpenCover.Profiler, необходимо для работы приложения. Можно опустить, если предварительно зарегестрировать вручную с помощью regsvr32.exe. Если у текущего пользователя нет прав админа, нужно использовать -register:user
  • -returntargetcode — Указывает, что нужно возвращать errorlevel, полученный приложением, указаным в параметре -target. Если опустить этот параметр и, например, у вас упадет какой-то тест, то приложение не остановит работу. Необходим, если вы используете анализ покрытия в контексте Continuous Integration, так как можно без проблем совместить анализ с обычным прогоном юнит-тестов и избежать их повторного запуска.

Итак, нам удалось настроить и запустить OpenCover и мы даже получили отчет в формате xml на много тысяч строк, который содержит очень подробные сведения о покрытии нашего кода. Однако есть проблема — он абсолютно нечитабелен. А хочется наглядно увидеть, что и как покрыто.

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

  • -reports:%reports% — Исходные файлы отчетов, если их несколько, разделяем точкой с запятой
  • -targetdir:%path% — Указывает, куда поместить сгенерированые отчеты
  • -reporttypes:%types% — Типы генерируемых отчетов. Мы используем -reporttypes:Html, нам хватает.

Получаем вот-такие отчеты:imageimage

Начало положено, покрытие кода анализируется. Дальше — на ваше усмотрение. Я, например, настроил нашу систему Continuous Integration таким образом, чтобы при покрытии ниже требуемого билд падал. Учитывая строгое отношение к завалившимся билдам, неплохо обеспечивает стабильное написание юнит-тестов :)

Автор: lavice

Источник

* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js