Объединяем Code Coverage от PHPUnit и phpspec

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



Стремиться к стопроцентному покрытию кода нет никакого смысла, однако понимать в среднем какой процент кода покрыт вашими тестами — хорошая метрика при непрерывном интегрировании.

Мы можем настроить оповещения при падении процента покрытия, например, ниже 50, можем добавлять автоматические комментарии от ботов в пул реквестах, показывать тенденцию изменения Code Coverage на графиках с течением времени и т.д.

image

Но что делать, если вы используете несколько библиотек для тестирования? Как получить общее покрытие кода?

Тут на помощь приходит библиотека phpcov

Итак, что мы будем делать при каждом билде (на примере Travis-CI):

  • Запускаем тесты PHPUnit, генерируем Code Coverage
  • Запускаем тесты phpspec, генерируем Code Coverage
  • Объединяем (merge) полученные результаты в единое покрытие
  • Сохраняем результаты для последующего анализа и отображения

Для примера, возьмем проект на Symfony3, где используются PHPUnit совместно с phpspec.

Конфигурация тестов PHPUnit может выглядеть следующим образом:

phpunit.xml
<?xml version="1.0" encoding="UTF-8"?>

<!-- https://phpunit.de/manual/current/en/appendixes.configuration.html -->
<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:noNamespaceSchemaLocation="http://schema.phpunit.de/4.8/phpunit.xsd"
         backupGlobals="false"
         colors="true"
         bootstrap="app/autoload.php"
>
    <php>
        <ini name="error_reporting" value="-1" />
        <server name="KERNEL_DIR" value="app/" />
    </php>

    <testsuites>
        <testsuite name="Project Test Suite">
            <directory>tests</directory>
        </testsuite>
    </testsuites>

    <filter>
        <whitelist>
            <directory>src</directory>
            <exclude>
                <directory>src/*Bundle/Resources</directory>
                <directory>src/*/*Bundle/Resources</directory>
                <directory>src/*/Bundle/*Bundle/Resources</directory>
            </exclude>
        </whitelist>
    </filter>

    <logging>
        <log type="coverage-php" target="/tmp/coverage_phpunit.cov"/>
    </logging>
</phpunit>


Это стандартный конфиг, за исключением нескольких строк:

<logging>
    <log type="coverage-php" target="/tmp/coverage_phpunit.cov"/>
</logging>

Здесь мы говорим, что будет использован PHP формат отчета о покрытии и кладем файл в нужную папку.

Далее похожие действия делаем с phpspec:

# phpspec.yml
...
extensions:
    PhpSpecCodeCoverage\CodeCoverageExtension:
        format:
            - php
        output:
            php: /tmp/coverage_phpspec.cov

Осталось запустить это всё дело при каждом билде и смержить результаты:

# .travis.yml
...

script:
  - bin/phpspec run --format=pretty
  - bin/phpunit
  - wget https://phar.phpunit.de/phpcov.phar && php phpcov.phar merge /tmp --clover coverage.xml

phpcov собирает все данные из вашей папки, объединяет их и сохраняет результат в формате Clover, который можно использовать для отображения покрытия кода, в том числе, и такого бейджа

Вот и всё. Пишите тесты, рефакторите с удовольствием.

UPD: бейджи, комментарии в пул реквестах и многое другое делается с помощью сервиса codecov.io (или как альтернатива — coveralls.io)

После настройки репозитория, интеграция с Travis-CI делается в одну строку:

# .travis.yml
...
after_success:
  - bash <(curl -s https://codecov.io/bash)


Codecov автоматически возьмет сгенерированный отчет в формате Clover и проанализирует его.

Также, при установке дополнения в браузер, можно прямо на Github видеть, какие строки покрыты тестами, а какие нет:

image
image
  • +16
  • 5,5k
  • 7
SimpleWeek 13,12
Персональный менеджер задач
Поделиться публикацией
Ой, у вас баннер убежал!

Ну, и что?
Реклама
Комментарии 7
  • 0
    Самое интересное и не рассказали — как бейджик сделать? ))
    • +2
      https://coveralls.io/ — тут есть инструкция.
      • 0
        Спасибо. Думал, что это бейджик от Travis, но там такого не нашел.
        • 0
          добавил в статью еще альтернативный вариант
    • +1
      Сегодня та или иная библиотека на Github, у которой нет тестов, уже не воспринимается серьезно.

      Кем не воспринимается? Значит ли это, что тесты должны быть в любой библиотеке, просто «шоб було»?

      Тесты помогают нам смело делать рефакторинг и быть уверенными, что модуль, класс или функция работают так, как это задумывалось. Они позволяют нам тестировать наш код на разных версиях PHP и выявлять ошибки заранее. Это гарант качества и стабильности вашего кода.

      Это если сами тесты написаны правильно. А кто будет гарантировать качество самих тестов? Тесты тоже пишутся людьми и само по себе их наличие, не дает никакой гарантии качества и стабильности кода. Тем более, что «Стремиться к стопроцентному покрытию кода нет никакого смысла», это означает, что кто-то решает что покрыть тестами, а что — нет. Всегда ли это решение разумно и обосновано?
      • +1
        Наличие тестов, проходящих мало-мальское код-ревью (просто чтобы убедиться, что они реально что-то тестируют) или просто автоматически полученная метрика покрытия, близкая к 100%, уменьшает вероятность ошибки. Грубо, если я делаю одну ошибку на 10 строк кода случайным образом, то проходящие тесты дают основание считать, что в основном коде остались ошибки в одной строке из 100. Это не гарантия, конечно, но статистико-вероятностная оценка количества ошибок.
      • 0
        Кем не воспринимается? Значит ли это, что тесты должны быть в любой библиотеке, просто «шоб було»?


        Не воспринимается разработчиками. Если я вижу выбор среди нескольких бандлов/модулей, не последнее место будет занимать критерий выбора по наличию test suite.

        Да что тут говорить, когда делаешь PR тебя в большинстве случаях попросят добавить и тесты, хотябы как самый свежий пример — изменение в этом плане политики в репозитории Yii фреймворка.

        А кто будет гарантировать качество самих тестов? Всегда ли это решение разумно и обосновано?


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

        Еще раз подчеркну, тесты гарантируют вам что после рефакторинга ваш код работает так, как вы это задумывали до него. Меньше траты времени на поддержку -> меньше багов -> более стабильный код

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

        Самое читаемое