Сегодня та или иная библиотека на 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
Поделиться с друзьями
-->

Комментарии (7)


  1. AlexLeonov
    27.11.2016 09:43

    Самое интересное и не рассказали — как бейджик сделать? ))


    1. zviryatko
      27.11.2016 11:03
      +2

      https://coveralls.io/ — тут есть инструкция.


      1. AlexLeonov
        27.11.2016 22:13

        Спасибо. Думал, что это бейджик от Travis, но там такого не нашел.


        1. borNfree
          27.11.2016 22:16

          добавил в статью еще альтернативный вариант


  1. Alex_T666
    28.11.2016 13:47
    +1

    Сегодня та или иная библиотека на Github, у которой нет тестов, уже не воспринимается серьезно.

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

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

    Это если сами тесты написаны правильно. А кто будет гарантировать качество самих тестов? Тесты тоже пишутся людьми и само по себе их наличие, не дает никакой гарантии качества и стабильности кода. Тем более, что «Стремиться к стопроцентному покрытию кода нет никакого смысла», это означает, что кто-то решает что покрыть тестами, а что — нет. Всегда ли это решение разумно и обосновано?


    1. VolCh
      01.12.2016 11:38
      +1

      Наличие тестов, проходящих мало-мальское код-ревью (просто чтобы убедиться, что они реально что-то тестируют) или просто автоматически полученная метрика покрытия, близкая к 100%, уменьшает вероятность ошибки. Грубо, если я делаю одну ошибку на 10 строк кода случайным образом, то проходящие тесты дают основание считать, что в основном коде остались ошибки в одной строке из 100. Это не гарантия, конечно, но статистико-вероятностная оценка количества ошибок.


  1. borNfree
    28.11.2016 13:54

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


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

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

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


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

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