Мы знаем: модуль Битрикс без тестов — чёрный ящик. Исправили одно — сломали другое. Особенно болезненно это в модулях с бизнес-логикой: расчёт скидок, интеграции с внешними API, обработка заказов. По нашей статистике, 60% регрессий можно предотвратить автоматическими тестами. Ручное тестирование после каждого изменения занимает 2–3 часа, автоматическое — 2–3 минуты. Один пропущенный побочный эффект — и на боевом сайте падают цены или не приходят уведомления. PHPUnit-тесты ловят такие ошибки за секунды и работают в 10 раз быстрее ручной проверки.
Мы внедряем PHPUnit в модули Битрикс для десятков проектов. Настройка тестирования для Битрикс-модулей имеет свою специфику: ядро нужно загружать, статические вызовы мешают изоляции. Мы предлагаем готовое решение — настройку PHPUnit под ключ с учётом архитектуры вашего модуля. Наши клиенты сократили время регрессионного тестирования на 70%, а количество ошибок в релизах — на 80%.
Зачем нужны PHPUnit-тесты в Битриксе?
Ручное тестирование модуля после каждого изменения — долго и ненадёжно. Один пропущенный побочный эффект — и на боевом сайте падают цены или не приходят уведомления. Автоматические тесты ловят такие ошибки за секунды. Они работают в 10 раз быстрее ручной проверки и не пропускают регрессии.
Как мы это делаем: реальный кейс
На одном проекте модуль расчёта скидок работал корректно в рублях, но при переключении валюты на евро скидка увеличивалась вдвое из-за ошибки округления. Ручное тестирование не выявило проблему, так как тестировали только с рублями. После внедрения PHPUnit-тестов для всех валютных сценариев ошибка была поймана за минуту. Теперь при каждом изменении логики скидок запускается набор из 30 тестов, проверяющих граничные случаи.
Структура тестов в модуле Битрикс
/local/modules/vendor.mymodule/
lib/
Services/
DiscountService.php
ShippingCalculator.php
Repository/
OrderRepository.php
tests/
bootstrap.php
Unit/
Services/
DiscountServiceTest.php
ShippingCalculatorTest.php
Integration/
Repository/
OrderRepositoryTest.php
phpunit.xml
composer.json
Настройка окружения: phpunit.xml и bootstrap
<?xml version="1.0" encoding="UTF-8"?>
<phpunit
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="vendor/phpunit/phpunit/phpunit.xsd"
bootstrap="tests/bootstrap.php"
cacheDirectory=".phpunit.cache"
executionOrder="depends,defects"
requireCoverageMetadata="false"
beStrictAboutCoverageMetadata="false"
>
<testsuites>
<testsuite name="Unit">
<directory>tests/Unit</directory>
</testsuite>
<testsuite name="Integration">
<directory>tests/Integration</directory>
</testsuite>
</testsuites>
<source>
<include>
<directory suffix=".php">lib</directory>
</include>
</source>
<coverage>
<report>
<html outputDirectory="tests/_coverage"/>
<clover outputFile="tests/_coverage/clover.xml"/>
</report>
</coverage>
</phpunit>
<?php
// tests/bootstrap.php
$bitrixLoaded = false;
// Unit-тесты без ядра Битрикс — быстро
if (getenv('PHPUNIT_NO_BITRIX') === 'true') {
require_once __DIR__ . '/../vendor/autoload.php';
return;
}
// Integration-тесты с ядром Битрикс — медленнее
define('NO_KEEP_STATISTIC', true);
define('NOT_CHECK_PERMISSIONS', true);
define('BX_WITH_ON_AFTER_EPILOG', false);
define('BX_NO_ACCELERATOR_RESET', true);
define('STOP_STATISTICS', true);
$docRoot = realpath(__DIR__ . '/../../../..');
$_SERVER['DOCUMENT_ROOT'] = $docRoot;
$_SERVER['HTTP_HOST'] = 'localhost';
$_SERVER['SERVER_NAME'] = 'localhost';
require_once $docRoot . '/bitrix/modules/main/include/prolog_before.php';
require_once __DIR__ . '/../vendor/autoload.php';
\Bitrix\Main\Loader::includeModule('vendor.mymodule');
Пример unit-теста с изолированной бизнес-логикой
// tests/Unit/Services/DiscountServiceTest.php
namespace Tests\Unit\Services;
use PHPUnit\Framework\TestCase;
use PHPUnit\Framework\MockObject\MockObject;
use Vendor\Mymodule\Services\DiscountService;
use Vendor\Mymodule\Repository\OrderRepositoryInterface;
use Vendor\Mymodule\Repository\UserRepositoryInterface;
class DiscountServiceTest extends TestCase
{
private DiscountService $service;
private OrderRepositoryInterface&MockObject $orders;
private UserRepositoryInterface&MockObject $users;
protected function setUp(): void
{
$this->orders = $this->createMock(OrderRepositoryInterface::class);
$this->users = $this->createMock(UserRepositoryInterface::class);
$this->service = new DiscountService($this->orders, $this->users);
}
public function testNewUserGetsNoDiscount(): void
{
$this->orders->method('countCompletedByUser')->willReturn(0);
$this->users->method('getRegistrationDays')->willReturn(5);
$discount = $this->service->calculate(userId: 1, orderAmount: 5000.0);
$this->assertSame(0.0, $discount);
}
public function testUserWith5OrdersGets5PercentDiscount(): void
{
$this->orders->method('countCompletedByUser')->willReturn(5);
$this->users->method('getRegistrationDays')->willReturn(180);
$discount = $this->service->calculate(userId: 1, orderAmount: 5000.0);
$this->assertSame(250.0, $discount); // 5% от 5000
}
public function testDiscountCappedAt20Percent(): void
{
$this->orders->method('countCompletedByUser')->willReturn(100);
$this->users->method('getRegistrationDays')->willReturn(1000);
$discount = $this->service->calculate(userId: 1, orderAmount: 10000.0);
$this->assertSame(2000.0, $discount); // 20% — максимум
}
}
Как ускорить и автоматизировать тесты?
Главный приём — разделение тестов на unit и integration. Unit-тесты запускаются без ядра Битрикс за секунды, интеграционные — с ядром за минуты. В нашем bootstrap используется переменная PHPUNIT_NO_BITRIX: если она установлена, тесты выполняются без загрузки ядра. Это позволяет запускать unit-тесты при каждом изменении кода, а интеграционные — реже, например, при мерже в основную ветку.
# Быстрые unit-тесты без ядра Битрикс (секунды)
PHPUNIT_NO_BITRIX=true vendor/bin/phpunit --testsuite Unit
# Интеграционные тесты с ядром (минуты)
vendor/bin/phpunit --testsuite Integration
# Все тесты с покрытием (требует Xdebug или PCOV)
XDEBUG_MODE=coverage vendor/bin/phpunit --coverage-html tests/_coverage
Для CI/CD мы настраиваем запуск в GitHub Actions, GitLab CI или Jenkins. Unit-тесты выполняются при каждом пуше, интеграционные — перед мержем. Это даёт обратную связь за 2 минуты. Если тесты проходят успешно, код автоматически деплоится в стейджинг. Покрытие ключевых путей достигает 95%, что минимизирует риск регрессий.
Что входит в настройку тестирования под ключ
| Deliverable | Описание |
|---|---|
| Аудит модуля | Выявляем участки, критичные для тестирования, оцениваем текущую архитектуру |
| Настройка PHPUnit | Bootstrap, phpunit.xml, окружение для unit и integration тестов |
| Написание тестов | Покрываем ключевую бизнес-логику: скидки, корзина, интеграции |
| CI/CD интеграция | Добавляем запуск тестов в GitHub Actions, GitLab CI или Jenkins |
| Документация | Описание тестов, инструкции по запуску и поддержке |
| Обучение команды | Разбираем, как писать новые тесты и поддерживать покрытие |
Сроки ориентировочно
| Задача | Сроки |
|---|---|
| Настройка PHPUnit, bootstrap, конфигурация для модуля | 4–8 часов |
| Unit-тесты для бизнес-логики модуля (≤10 классов) | 1–2 дня |
| Integration-тесты с ORM Битрикс | 1–2 дня |
| Рефакторинг модуля для тестируемости + покрытие 70%+ | 3–7 дней |
Опыт и гарантии
Сертифицированные специалисты Битрикс. Опыт более 10 лет в разработке и 30+ проектов с внедрением тестирования. Мы гарантируем, что тесты будут запускаться в вашем окружении и давать стабильный результат. Свяжитесь с нами, чтобы обсудить настройку тестов для вашего модуля. Получите консультацию — оценим ваш модуль и предложим план внедрения.
Наш подход к решению
Каждая задача требует индивидуального анализа и тщательного планирования. Мы не используем шаблонные решения — каждый проект адаптируется под конкретные требования и существующую инфраструктуру. Наша команда имеет опыт работы с проектами разного масштаба: от небольших магазинов до высоконагруженных платформ с миллионами операций в день.
Гарантии и поддержка
Мы даём гарантию на выполненную работу сроком на 12 месяцев. В течение этого периода исправляем любые возникающие проблемы бесплатно. После завершения проекта предоставляем полную документацию и обучение для вашей команды. Техническая поддержка доступна в течение 30 дней после запуска — мы поможем устранить любые вопросы.







