Написання unit-тестів для модулів 1С-Бітрікс

Вступ На одному проєкті у сфері логістики модуль розрахунку доставки видавав некоректні тарифи після кожного оновлення — через відсутність unit-тестів. Після рефакторингу та написання тестів помилки зникли, а час на внесення змін скоротився вдвічі. Вартість регресій впала на 70%, а бюджет на підт
Послуги, які ми пропонуємо
Показано 1 з 1Усі 1626 послуг
Написання unit-тестів для модулів 1С-Бітрікс
Середній
~1-2 тижні

Наші компетенції:

Часті запитання

Останні роботи

  • image_website-b2b-advance_0.webp
    Розробка сайту компанії B2B ADVANCE
    1443
  • image_bitrix-bitrix-24-1c_fixper_448_0.webp
    Розробка веб-сайту для компанії ФІКСПЕР
    1013
  • image_bitrix-bitrix-24-1c_development_of_an_online_appointment_booking_widget_for_a_medical_center_594_0.webp
    Розробка на базі Бітрікс, Бітрікс24, 1С для компанії Development of an Online
    752
  • image_bitrix-bitrix-24-1c_mirsanbel_458_0.webp
    Розробка на базі 1С Підприємство для компанії МИРСАНБЕЛ
    873
  • image_crm_dolbimby_434_0.webp
    Розробка сайту на CRM Бітрікс24 для компанії DOLBIMBY
    795
  • image_crm_technotorgcomplex_453_0.webp
    Розробка на базі Бітрікс24 для компанії ТЕХНОТОРГКОМПЛЕКС
    1155

Вступ

На одному проєкті у сфері логістики модуль розрахунку доставки видавав некоректні тарифи після кожного оновлення — через відсутність unit-тестів. Після рефакторингу та написання тестів помилки зникли, а час на внесення змін скоротився вдвічі. Вартість регресій впала на 70%, а бюджет на підтримку модуля знизився вдвічі. Це типова ситуація: код Бітрікс-модулів часто щільно пов'язаний з ядром, що робить його складним для тестування. Досвід нашої команди в десятках проєктів підтверджує: правильна архітектура та unit-тести скорочують час розробки нових фіч вдвічі та знижують кількість багів на 70%. Ми регулярно стикаємося з проєктами, де бізнес-логіка не ізольована, і написання тестів вимагає попереднього рефакторингу. Однак навіть у таких випадках unit-тести окупаються протягом перших місяців експлуатації.

Чому unit-тести в Бітрікс складніші, ніж в інших проєктах?

Типові проблеми, які ми бачимо на старті:

  • Щільна пов'язаність з ядром. Класи успадковують CBitrixComponent або викликають CIBlockElement напряму. Будь-який тест вимагає ініціалізації всього оточення.
  • Відсутність інтерфейсів. Репозиторії часто не виділені в окремі класи. Натомість SQL-запити розкидані по методах.
  • Глобальні стани. Бітрікс використовує глобальні змінні ($APPLICATION, $DB) та синглтони. Це ламає ізоляцію тестів.
  • Повільний bootstrap. Завантаження ядра через prolog_before.php займає 1–3 секунди, що робить прогін тисячі тестів неприйнятно довгим.

Через ці фактори багато розробників відмовляються від unit-тестування. Але ми знайшли підхід, який робить його ефективним.

Принцип тестованої архітектури

Перший крок — виділити бізнес-логіку в окремі класи з чіткими інтерфейсами. Не робіть так:

// Бізнес-логіка змішана з інфраструктурою — неможливо протестувати ізольовано public function calculateDiscount(int $userId): float { $user = \CUser::GetByID($userId)->Fetch(); // статичний виклик Бітрікс $orders = \CSaleOrder::GetList([], ['USER_ID' => $userId])->Fetch(); return $orders['count'] > 10 ? 0.15 : 0.05; } 

Натомість інжектуйте залежності:

// Логіка відокремлена, залежності інжектуються class DiscountCalculator { public function __construct( private UserRepositoryInterface $users, private OrderRepositoryInterface $orders, ) {} public function calculate(int $userId): float { $user = $this->users->findById($userId); $orderCount = $this->orders->countByUserId($userId); return $orderCount > 10 ? 0.15 : 0.05; } } 

Репозиторії реалізуються через Бітрікс API в продакшн-коді та через моки в тестах. Такий рефакторинг окупається вже після першого циклу змін. Детальніше про впровадження залежностей у документації Бітрікс.

Інфраструктура тестів

Налаштовуємо PHPUnit з двома bootstraps: один для чистих unit-тестів (без ядра, лише Composer autoload), другий — для інтеграційних, що завантажують Бітрікс.

Приклад bootstrap для інтеграційних тестів:

// tests/bootstrap.php define('NO_KEEP_STATISTIC', true); define('NOT_CHECK_PERMISSIONS', true); define('BX_WITH_ON_AFTER_EPILOG', false); define('BX_NO_ACCELERATOR_RESET', true); $_SERVER['DOCUMENT_ROOT'] = realpath(__DIR__ . '/../../../..'); require_once $_SERVER['DOCUMENT_ROOT'] . '/bitrix/modules/main/include/prolog_before.php'; \Bitrix\Main\Loader::includeModule('your.module'); 

Для ізольованих тестів — окремий bootstrap без prolog_before.php. Це прискорює прогін у 10–50 разів.

Приклади unit-тестів

Тест бізнес-логіки (без ядра):

class DiscountCalculatorTest extends TestCase { private DiscountCalculator $calculator; protected function setUp(): void { $this->calculator = new DiscountCalculator( users: $this->createStub(UserRepositoryInterface::class), orders: $this->createConfiguredMock( OrderRepositoryInterface::class, ['countByUserId' => 5] ), ); } public function testLessThan10OrdersGivesBasicDiscount(): void { $this->assertSame(0.05, $this->calculator->calculate(1)); } public function testMoreThan10OrdersGivesPremiumDiscount(): void { $repo = $this->createConfiguredMock( OrderRepositoryInterface::class, ['countByUserId' => 15] ); $calc = new DiscountCalculator($this->createStub(UserRepositoryInterface::class), $repo); $this->assertSame(0.15, $calc->calculate(1)); } } 

Інтеграційні тести з ядром використовуємо лише для перевірки ORM або складних ланцюжків викликів. Вони запускаються окремо, не в основному наборі.

Який ROI від unit-тестів?

Впровадження unit-тестів скорочує час на налагодження на 70% та знижує вартість підтримки вдвічі завдяки ранньому виявленню регресій. У середньому на одну бізнес-операцію (розрахунок, валідація) йде від 2 до 6 годин написання тестів. Повний цикл для модуля середнього розміру — 2–5 днів. Терміни залежать від поточної архітектури та необхідності рефакторингу. Якщо ви хочете підвищити стабільність проєкту, зв'яжіться з нами для аудиту тестованості.

Порівняння підходів

Критерій Ізольовані unit-тести Інтеграційні з ядром
Швидкість виконання 0.01–0.1 сек 1–5 сек
Залежність від БД Ні Так
Вимагають моків Так Ні
Покривають бізнес-логіку Так Так
Покривають інфраструктуру Ні Так
Простота налагодження Висока Середня

Ізольовані тести в 50 разів швидші — для більшості сценаріїв обираємо їх.

Покриття та пріоритизація

Не потрібно покривати тестами 100% коду. Пріоритети:

Пріоритет Що тестуємо
Високий Розрахунки цін, знижок, вартості доставки
Високий Бізнес-логіка станів (статусна машина)
Високий Парсери та маппінг даних (імпорт з 1С, Excel)
Середній Валідатори вхідних даних
Середній Алгоритми формування звітів
Низький Шаблони компонентів, UI-логіка

Цільове покриття для ключової бізнес-логіки — 80%+. Для інфраструктурного коду (репозиторії, адаптери) достатньо інтеграційних тестів. Це дає баланс між швидкістю та надійністю.

Що входить у написання unit-тестів

  1. Аудит коду модуля на тестованість, рефакторинг точок впровадження залежностей.
  2. Налаштування PHPUnit з bootstrap для Бітрікс-оточення.
  3. Написання тестів для бізнес-логіки: розрахунки, статусні машини, парсери.
  4. Налаштування звіту покриття через Xdebug.
  5. Інтеграція запуску тестів у CI (GitHub Actions / GitLab CI).
  6. Документація із запуску тестів та додавання нових.

Ми гарантуємо якість: досвід наших інженерів — понад 10 років у Бітрікс-розробці. Замовте написання unit-тестів під ключ — отримайте стабільний і легкопідтримуваний код. Оцінимо ваш проєкт безкоштовно, просто зв'яжіться з нами.

Типові помилки при написанні тестів для Бітрікс

  • Спроба завантажувати ядро для кожного тесту: використовуйте два bootstrap'и.
  • Використання реальної бази даних в unit-тестах: мокайте репозиторії.
  • Ігнорування кешування результатів: скидайте кеш між тестами.
  • Тестування захищених методів через рефлексію: виділіть логіку в публічні методи.