Создавайте критические покрытия модульных тестов. О, ты не в теме? Вы когда-нибудь пробовали это? Вас может раздражать, что я даже пытаюсь об этом говорить. Давайте просто расплавим это расплавленное лицо
Основное преимущество модульных тестов заключается в том, что наш код ведет себя так, как мы говорим. Это также эффективная форма документации, дающая нам уверенность в том, что мы сможем улучшить нашу кодовую базу посредством рефакторинга. Даже со всеми этими преимуществами лучшие разработчики, скорее всего, будут экономить на их написании, если не будет немедленного штрафа. Мы познакомимся с инструментами, позволяющими сбросить сборку, когда цели по охвату не достигаются, и это принесет чистую радость.
Наша отправная точка заключается в том, что у нас есть сборка непрерывной интеграции (CI), которая работает python -m unittest discover
, как описано в документации. Начать работу с измерением покрытия юнит-тестами так же просто, как pip install coverage
в Python (подробнее). Если у вас есть скрипт Python для запуска тестов, мы будем собирать данные о покрытии, выполнив следующее:
def run_tests(): """ Run the unit tests, collect coverage data and output an xml report. Adjust the cwd to match your test root folder. """ subprocess.check_call( [ "coverage", "run", "-m", "unittest", "discover", ], cwd="test", ) subprocess.check_call(["coverage", "xml"], cwd="test")
Чтобы увидеть красивый HTML-отчет, используйте следующий код:
def open_html_coverage_report(): subprocess.check_call( ["coverage", "html", "-d", "_coverage_data"], cwd="test" ) subprocess.check_call(["open", "_coverage_data/index.html"], cwd="test")
После того, как вы потратили некоторое время на изучение отчета и составление картины вашего текущего покрытия, мы делаем первые шаги в установлении закона. Но самым добрым, самым нежным образом.
def check_coverage(): """ Generate a coverage report and fail if minimum coverage is not met. """ subprocess.check_call(["coverage", "xml", "--fail-under=85"], cwd="test")
Сейчас вы смотрите на один из двух результатов:
В первом сценарии все прошло успешно. Если это совершенно новый проект и вы устанавливаете забор перед тем, как взять щенка, поздравляем! Добавление этой проверки в новый проект — наименее болезненный способ. Также может случиться так, что вы, просто случайно, получили высокий уровень освещения проекта без отчетности, но это маловероятно.
Во втором сценарии вы видите такое сообщение:
Coverage failure: total of 56 is less than fail-under=85
Никто не злится. Избиения не будут продолжаться, пока освещение не улучшится. Мы поступим максимально гуманно. Принятие. Просто установите порог, соответствующий текущему уровню покрытия. Вот и все. Действительно. Даже если вы больше ничего не делаете, в каждом пулл-реквесте убеждать, что вы не допустите ухудшения уровня покрытия, — это большой шаг. И вам больше не нужно пожимать плечами, когда вас спрашивают, какое у вас покрытие юнит-тестами.
Теперь у вас есть команды для подключения вашего локального тестирования к запуску тестов с данными о покрытии и проверке цели. Запустите ту же команду в своем CI, и я буду рад попрощаться с вами. Но если хочешь потусить, у меня осталось несколько трюков для Дженкинса.
На данный момент наша работа включает в себя создание данных о покрытии в формате XML, которые подключаемый модуль Cobertura будет использовать для создания красивого отчета в пользовательском интерфейсе Jenkins и установки статуса сборки. Начните с установки плагина, если у вас его еще нет. Вот ссылка: https://plugins.jenkins.io/cobertura/
Прежде чем прыгнуть в Jenkinsfile
, нужно прояснить кое-что. Вы хотите, чтобы ваши сценарии имели локальную тестовую команду, которая использует параметр --fail-under
, и тестовую команду CI, которая его не включает. В Jenkins мы всегда хотим создать отчет XML и запустить этап cobertura. Плагин Cobertura проверит уровень покрытия и завершит сборку (docs).
Вот как будет выглядеть наш файл Jenkins после запуска тестов:
cobertura autoUpdateHealth: false, autoUpdateStability: false, coberturaReportFile: '**/test/coverage.xml', conditionalCoverageTargets: '70, 0, 0', failUnhealthy: false, failUnstable: true, lineCoverageTargets: '80, 0, 85', maxNumberOfBuilds: 0, methodCoverageTargets: '80, 0, 0', onlyStable: false, sourceEncoding: 'ASCII', zoomCoverageChart: false
Мы рассмотрим три наиболее важных параметра:
coberturaReportFile
должно соответствовать местоположению, в котором данные покрытия XML сохраняются командойcoverage
.failUnstable
помечает сборку как нестабильную, когда она ниже порогового значения. Я предпочитаю считать сборку исправной, если ее не удается собрать, и нестабильной, если сборка завершается ошибкой на этапе после сборки.lineCoverageTargets
содержит три числа, третье из которых является нашей целью. Вы можете углубиться в другие области применения, такие как условные выражения, но я оставлю это для вас.
Теперь у нас есть сборка CI, которая потерпит неудачу, если наш порог покрытия не будет достигнут! Я ограничу объем этой статьи этой вехой. В идеале у вас уже есть система управления версиями, настроенная на запуск CI при открытии запроса на включение и блокировку слияний на основе результатов, и это просто прекрасно вписывается в этот поток.
Отсюда команда должна согласиться выполнять дух этого контроля качества. Чтобы быть полностью эффективным, каждый в процессе обзора несет ответственность за то, чтобы всегда стремиться поднять цель выше и делать это всякий раз, когда это возможно. Никому не позволено понизить его. Любые занятия или файлы, которые нужно пропустить, тщательно рассматриваются и согласовываются. Наконец, некачественные тесты выявляются.
Что такое хорошая цель? Без сомнения, это глубокая тема, но я раскрою ее практическим опытом. Это 85%. С проектами, которые начинаются с охвата, и с теми, которые представили его спустя годы, 85% разумны, беспрепятственны и полезны. Более высокое покрытие достижимо, но, как правило, бессмысленно. Каждый проект содержит какой-то шаблонный код и простой, сложный для тестирования код, который практически не имеет ценности. 85% допускают это без создания явных фильтров.
Мы выполнили шаги по внедрению порогов покрытия в локальные сборки и нашу систему непрерывной интеграции, чтобы аккуратно поддерживать и повышать качество ваших проектов. Вы не просто делаете хорошо; ты делаешь хорошо. Как Супермен.