Spec-Zone.ru › PHPUnit

Покрытие кода

Wikipedia:

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

В этой главе вы узнаете о функциональности покрытия кода PHPUnit, которая дает представление о том, какие части кода приложения выполняются при запуске тестов. Она использует библиотеку php-code-coverage, которая, в свою очередь, использует функциональность покрытия кода, предоставляемую расширениями PCOV или Xdebug для PHP.

Примечание

Если при запуске тестов вы видите предупреждение о том, что драйвер покрытия кода недоступен, это означает, что вы используете бинарный файл PHP CLI (php) и не загрузили PCOV или Xdebug.

Примечание

Если вы хотите использовать Xdebug для сбора данных о покрытии кода, вам необходимо активировать режим покрытия coverage Xdebug.

PHPUnit может генерировать отчет о покрытии кода в формате HTML, а также XML-файлы журналов с информацией о покрытии кода в различных форматах (Clover, Cobertura, Crap4J, PHPUnit). Информация о покрытии кода также может быть представлена в текстовом формате (и выведена в STDOUT) и экспортирована в виде кода PHP для дальнейшей обработки.

Обратитесь к разделу Инструмент командной строки для запуска тестов для списка параметров командной строки, которые управляют функциональностью покрытия кода, а также к Элемент <source> и Элемент <coverage> для соответствующих параметров конфигурации для отчета о покрытии кода.

Метрики программного обеспечения для покрытия кода

Существуют различные метрики программного обеспечения для измерения покрытия кода:

Покрытие строк

Метрика программного обеспечения Покрытие строк измеряет, была ли выполнена каждая исполняемая строка.

Покрытие ветвей

Метрика программного обеспечения Покрытие ветвей измеряет, принимало ли значение булево выражение каждой управляющей структуры как true, так и false при выполнении набора тестов.

Покрытие путей

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

Покрытие функций и методов

Метрика программного обеспечения Покрытие функций и методов измеряет, была ли вызвана каждая функция или метод. php-code-coverage рассматривает функцию или метод как покрытый только тогда, когда все его исполняемые строки покрыты.

Покрытие классов и трейтов

Метрика программного обеспечения Покрытие классов и трейтов измеряет, покрыт ли каждый метод класса или трейта. php-code-coverage рассматривает класс или трейт как покрытый только тогда, когда все его методы покрыты.

Индекс антипаттернов риска изменений (CRAP)

Индекс антипаттернов риска изменений (CRAP) рассчитывается на основе цикломатической сложности и покрытия кода блока кода. Код, не слишком сложный и имеющий достаточное покрытие тестами, будет иметь низкий индекс CRAP. Индекс CRAP можно снизить, написав тесты и переработав код, чтобы уменьшить его сложность.

Библиотека, используемая PHPUnit, поддерживает все перечисленные выше метрики программного обеспечения для покрытия кода. Для отчета о покрытии ветвей и путей данные покрытия кода должны собираться с помощью Xdebug, так как PCOV поддерживает только покрытие строк.

Включение файлов

Обязательно настройте, какие файлы исходного кода вы считаете своими и, следовательно, хотите включить в отчет о покрытии кода. Поскольку другие функции PHPUnit также должны знать, какие файлы исходного кода вы считаете своими, рекомендуется настроить это в файле конфигурации XML (см. Элемент <include>). В качестве альтернативы, вы можете использовать параметр командной строки --coverage-filter командной строки.

Настройка includeUncoveredFiles доступна для настройки того, как используется фильтр:

  • includeUncoveredFiles="true" (по умолчанию) означает, что все файлы включены в отчет о покрытии кода, даже если ни одна строка кода такого файла не выполнена

  • includeUncoveredFiles="false" означает, что в отчет о покрытии кода включаются только файлы, в которых выполнена хотя бы одна строка кода

Для получения полного и честного отчета о покрытии кода настоятельно рекомендуется использовать значение по умолчанию.

Нацеливание на блоки кода

Атрибуты PHPUnit\Framework\Attributes\CoversClass, PHPUnit\Framework\Attributes\CoversMethod и PHPUnit\Framework\Attributes\CoversFunction могут использоваться в тестовом коде для указания блоков кода, которые класс тестов намерен охватить.

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

Пример 7.1 демонстрирует пример.

Пример 7.1 Класс тестов, который указывает, какой класс он хочет охватить
<?php declare(strict_types=1);
use PHPUnit\Framework\Attributes\CoversClass;
use PHPUnit\Framework\Attributes\UsesClass;
use PHPUnit\Framework\TestCase;

#[CoversClass(Invoice::class)]
#[UsesClass(Money::class)]
final class InvoiceTest extends TestCase
{
    public function testAmountInitiallyIsEmpty(): void
    {
        $this->assertEquals(new Money, (new Invoice)->amount());
    }
}

Атрибуты PHPUnit\Framework\Attributes\UsesClass, PHPUnit\Framework\Attributes\UsesMethod и PHPUnit\Framework\Attributes\UsesFunction могут использоваться для указания блоков кода, которые должны быть проигнорированы для покрытия кода, но которые разрешено использовать коду, который покрыт. Это объясняется в разделе о неожиданно покрытом коде.

В приведенном выше примере атрибут #[CoversClass(Invoice::class)] сообщает PHPUnit, что тесты этого класса тестов предназначены для покрытия кода класса Invoice. При запуске тестов этого класса тестов будет обрабатываться только информация о покрытии кода для класса Invoice, и информация о покрытии кода для всего остального кода, который также может быть запущен во время этих тестов, будет проигнорирована.

В приведенном выше примере атрибут #[UsesClass(Money::class)] сообщает PHPUnit, что ожидается и разрешено, что код из класса Money также будет запущен при запуске тестов этого класса тестов. Это важно, когда речь идет о рискованном тесте, когда он запускает код, который не должен запускаться.

Поскольку технически невозможно протестировать подкласс в изоляции от его базовых классов, атрибуты #[CoversClass] и #[UsesClass] учитывают класс, имя которого указано, а также все его родительские классы, если они есть.

Атрибут PHPUnit\Framework\Attributes\CoversNothing можно использовать для указания того, что тесты вообще не должны вносить вклад в покрытие кода. Это может быть полезно при написании интеграционных тестов и для обеспечения того, что вы генерируете покрытие кода только с помощью меньших тестов.

Пример 7.2 Тест, который указывает, что он не хочет вносить вклад в покрытие кода
<?php declare(strict_types=1);
use PHPUnit\Framework\Attributes\CoversNothing;
use PHPUnit\Framework\TestCase;

#[CoversNothing]
final class IntegrationTest extends TestCase
{
    public function testRegisteredUserCanLogIn(): void
    {
        // ...
    }
}

Игнорирование блоков кода

Иногда у вас есть блоки кода, или даже отдельные строки кода, которые нельзя протестировать, и которые вы можете захотеть проигнорировать во время анализа покрытия кода. PHPUnit позволяет сделать это с помощью аннотаций @codeCoverageIgnore, @codeCoverageIgnoreStart и @codeCoverageIgnoreEnd, которые могут использоваться в комментариях к коду в коде приложения:

Пример 7.3 Использование аннотаций @codeCoverageIgnore, @codeCoverageIgnoreStart и @codeCoverageIgnoreEnd
<?php declare(strict_types=1);
/**
 * @codeCoverageIgnore
 */
final class Foo
{
    public function bar(): void
    {
    }
}

final class Bar
{
    /**
     * @codeCoverageIgnore
     */
    public function foo(): void
    {
    }
}

if (false) {
    // @codeCoverageIgnoreStart
    print '*';
    // @codeCoverageIgnoreEnd
}

exit; // @codeCoverageIgnore

В приведенном выше примере аннотация @codeCoverageIgnore используется для игнорирования всего кода класса Foo, всего кода метода Bar::foo() и единственной строки кода с оператором exit;. Строка с оператором print '*'; игнорируется с помощью // @codeCoverageIgnoreStart и // @codeCoverageIgnoreEnd.

© 2005–2025 Sebastian Bergmann
Licensed under the Creative Commons Attribution 3.0 Unported License.
https://docs.phpunit.de/en/12.0/code-coverage.html

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API