К другим статьям
1С-БитриксPHPUnitТестированиеPHP
Для разработчиков

Тестирование модуля 1С-Битрикс в PHPUnit без установленного Битрикс

Большинство модулей Битрикс можно тестировать без установленного продукта. Для этого не нужно имитировать всё ядро: достаточно отделить чистую бизнес-логику и дать минимальные stubs тем API, которые действительно нужны сценарию.

В актуальной документации zr.paidaccess зафиксирован прогон 231 test / 748 assertions. Модуль поддерживает PHP 7.4+, а тестовая матрица охватывает PHP 7.4, 8.1 и 8.2. Это полезная комбинация: нижняя версия выявляет случайное использование нового синтаксиса, верхние — устаревшие вызовы и изменения строгости типов.

Что тестировать без Битрикс

В обычном PHPUnit-процессе хорошо проверяются:

  • расчёт периода, суммы и задолженности;
  • переходы статусов платежа;
  • идемпотентное завершение и отмена;
  • проверка подписи и нормализация webhook;
  • ledger, возвраты и распределение списаний;
  • DTO, presenters и форматирование данных;
  • правила зависимостей и production autoload.

Не стоит писать огромную копию ядра ради проверки IncludeComponent. Связку с реальной базой, событиями и административным UI лучше оставить интеграционным smoke-тестам на стенде.

Собственный загрузчик классов

Production map должен быть источником истины и для тестов:

final class ModuleClassLoader
{
    public static function register(string $moduleRoot): void
    {
        $map = require $moduleRoot . '/autoload.production.map.php';

        spl_autoload_register(static function (string $class) use ($map, $moduleRoot): void {
            if (!isset($map[$class])) {
                return;
            }

            require_once $moduleRoot . '/' . $map[$class];
        });
    }
}

Если provider-классы в production обнаруживаются отдельным loader, тестовый autoload должен повторять это правило либо подключать небольшой autoload.test-extra.map.php. В extra map нельзя складывать все классы подряд: иначе тесты пройдут, а поставка не загрузится на сайте.

Минимальные stubs

Stub реализует только контракт, использованный тестом. Например, для опций:

namespace Bitrix\Main\Config;

final class Option
{
    private static array $values = [];

    public static function get(string $module, string $name, $default = ''): string
    {
        return (string) (self::$values[$module][$name] ?? $default);
    }

    public static function set(string $module, string $name, string $value): void
    {
        self::$values[$module][$name] = $value;
    }
}

Этот пример требует PHP 7.4 из-за типизированного свойства. Он не пытается воспроизвести внутреннее хранение Битрикс. Если сервису нужен десяток методов Option, это сигнал выделить собственный интерфейс настроек.

Тест через контракт

Предпочтительнее подменять репозиторий модуля, а не DataManager:

final class InMemoryPaymentRepository implements PaymentRepository
{
    public array $items = [];

    public function save(Payment $payment): void
    {
        $this->items[$payment->id()] = $payment;
    }
}

Тест создаёт сервис с этой реализацией, запускает сценарий и проверяет итоговое состояние. D7 ORM остаётся в отдельном адаптере; его корректность подтверждают небольшие интеграционные тесты.

Architecture tests

Архитектурный тест — обычный PHPUnit-тест, который читает файлы или использует reflection. Полезно проверять:

  1. Все пути из production map существуют.
  2. Доменные namespaces не импортируют Admin и provider-specific классы.
  3. Внешний API используется только внутри соответствующего adapter.
  4. Публичный UI не зависит от административного.
  5. Test-extra map не скрывает пропуск в production map.

Простой контроль карты:

public function testProductionAutoloadFilesExist(): void
{
    $map = require MODULE_ROOT . '/autoload.production.map.php';

    foreach ($map as $class => $file) {
        self::assertFileExists(MODULE_ROOT . '/' . $file, $class);
    }
}

Такие проверки особенно ценны для модулей, которые устанавливаются копированием: ошибка autoload обнаруживается до выкладки.

Матрица PHP и воспроизводимость

Один и тот же composer test должен работать локально и в CI. Не подключайте bootstrap сайта и не читайте реальные опции. В fixture не должно быть доменов, ключей, персональных данных и дампа production-базы.

Для PHP 7.4 нельзя использовать attributes, enums, constructor property promotion и union types в production-коде. При этом прогон на 8.1/8.2 нужен, чтобы увидеть deprecation и несовместимость библиотек. Версию PHPUnit следует фиксировать через composer.lock.

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

Начните не со stub всего Битрикс, а с одного рискованного доменного сценария. Вынесите его из компонента, задайте интерфейс хранения и протестируйте на обычных объектах PHP. Затем добавьте минимальный stub для узкой системной зависимости и architecture test для autoload.

Именно сочетание unit-тестов, архитектурных ограничений и нескольких проверок на реальном стенде даёт устойчивый модуль. Полный набор тестов zr.paidaccess показывает, что значительную часть сложного D7-решения можно проверять без установленного ядра.

Нужен модуль или интеграция?

Разберём архитектуру вашей задачи на 1С-Битрикс

Опишите сценарий и ограничения проекта — предложу безопасную схему реализации, оценку и следующий шаг.