Настройка Codeception-тестов для 1С-Битрикс
Codeception — PHP-фреймворк для тестирования, который объединяет unit, functional и acceptance (E2E) тесты в одном инструменте. Для Битрикс это особенно удобно: можно писать functional-тесты, которые тестируют PHP-логику без браузера, и acceptance-тесты через WebDriver — всё в одном стеке, с одними хелперами, с одним конфигом.
Настройка Codeception-тестов для 1С-Битрикс
Установка и структура
# Устанавливаем в /local/ или в корень проекта
composer require --dev codeception/codeception
composer require --dev codeception/module-webdriver
composer require --dev codeception/module-phpbrowser
composer require --dev codeception/module-db
# Инициализация
vendor/bin/codecept bootstrap
Структура после инициализации:
tests/
Acceptance/
CatalogCest.php
CheckoutCest.php
AuthCest.php
Functional/
OrderCest.php
CatalogFilterCest.php
Unit/
PriceCalculatorTest.php
DeliveryZoneTest.php
_support/
AcceptanceTester.php
FunctionalTester.php
Helper/
Bitrix.php <- хелпер для Битрикс
_data/
dump.sql
codeception.yml
codeception.yml для Битрикс-проекта
namespace: Tests
support_namespace: Support
paths:
tests: tests
output: tests/_output
data: tests/_data
support: tests/_support
envs: tests/_envs
settings:
shuffle: false
lint: true
params:
- .env.test
extensions:
enabled:
- Codeception\Extension\RunFailed
suites:
acceptance:
actor: AcceptanceTester
modules:
enabled:
- WebDriver:
url: '%SITE_URL%'
browser: chrome
window_size: 1280x900
capabilities:
goog:chromeOptions:
args: ['--headless', '--no-sandbox']
host: selenium
port: 4444
- Db:
dsn: 'mysql:host=%DB_HOST%;dbname=%DB_NAME%'
user: '%DB_USER%'
password: '%DB_PASS%'
functional:
actor: FunctionalTester
modules:
enabled:
- Bitrix:
document_root: '%DOCUMENT_ROOT%'
- Db:
dsn: 'mysql:host=%DB_HOST%;dbname=%DB_NAME%'
user: '%DB_USER%'
password: '%DB_PASS%'
unit:
actor: UnitTester
Хелпер для Битрикс-окружения
// tests/_support/Helper/Bitrix.php
namespace Tests\Support\Helper;
use Codeception\Module;
class Bitrix extends Module
{
public function _beforeSuite(array $settings = []): void
{
$docRoot = $this->config['document_root'];
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'] = $docRoot;
if (!defined('B_PROLOG_INCLUDED')) {
require_once $docRoot . '/bitrix/modules/main/include/prolog_before.php';
}
}
public function loginAs(string $login, string $password): bool
{
global $USER;
$USER = new \CUser();
return (bool)$USER->Login($login, $password);
}
public function addProductToCart(int $productId, int $quantity = 1): int
{
\Bitrix\Main\Loader::includeModule('sale');
\Bitrix\Main\Loader::includeModule('catalog');
$basket = \Bitrix\Sale\Basket::loadItemsForFUser(
\CSaleBasket::GetBasketUserID(),
\Bitrix\Main\Context::getCurrent()->getSite()
);
$item = $basket->createItem('catalog', $productId);
$item->setField('QUANTITY', $quantity);
$basket->save();
return $basket->getOrderableItems()->count();
}
}
Functional-тест: заказ через Битрикс API
// tests/Functional/OrderCest.php
namespace Tests\Functional;
use Tests\Support\FunctionalTester;
class OrderCest
{
public function _before(FunctionalTester $I): void
{
// Очищаем корзину перед каждым тестом
$I->executeQuery('DELETE FROM b_sale_basket WHERE FUSER_ID = ?', [1]);
}
public function addItemAndCreateOrder(FunctionalTester $I): void
{
// Добавляем товар в корзину через хелпер
$I->loginAs('testuser', 'testpassword');
$count = $I->addProductToCart(42, 2); // товар ID=42, 2 штуки
$I->assertEquals(1, $count, 'В корзине должен быть 1 товар');
// Создаём заказ через Sale API
$I->executeCustomAction(function () {
\Bitrix\Main\Loader::includeModule('sale');
$basket = \Bitrix\Sale\Basket::loadItemsForFUser(1, 's1');
$order = \Bitrix\Sale\Order::create('s1', 1); // сайт, пользователь
$order->setBasket($basket);
$order->setField('CURRENCY', 'RUB');
$propertyCollection = $order->getPropertyCollection();
$prop = $propertyCollection->getPayerName();
$prop?->setValue('Тестовый Пользователь');
$result = $order->save();
return $result;
}, function ($result) use ($I) {
$I->assertTrue($result->isSuccess(), implode(', ', $result->getErrorMessages()));
});
// Проверяем, что заказ создан в базе
$I->seeInDatabase('b_sale_order', [
'USER_ID' => 1,
'CURRENCY' => 'RUB',
'STATUS_ID' => 'N',
]);
}
}
Acceptance-тест через WebDriver
// tests/Acceptance/CatalogCest.php
namespace Tests\Acceptance;
use Tests\Support\AcceptanceTester;
class CatalogCest
{
public function filterByBrandShowsCorrectProducts(AcceptanceTester $I): void
{
$I->amOnPage('/catalog/tools/');
$I->waitForElement('.catalog-filter', 10);
// Применяем фильтр по бренду
$I->checkOption('[data-filter="brand"][value="bosch"]');
$I->waitForElementNotVisible('.catalog-loading', 10);
// Проверяем URL
$I->seeInCurrentUrl('brand=bosch');
// Проверяем, что все карточки — Bosch
$I->seeNumberOfElementsGreaterThan('.product-card', 0);
$brands = $I->grabMultiple('.product-brand');
foreach ($brands as $brand) {
$I->assertEquals('Bosch', $brand);
}
}
}
Запуск тестов
# Все тесты
vendor/bin/codecept run
# Только acceptance
vendor/bin/codecept run acceptance
# Конкретный тест
vendor/bin/codecept run acceptance CatalogCest:filterByBrandShowsCorrectProducts
# С подробным выводом
vendor/bin/codecept run --steps --debug
Сроки
| Задача | Сроки |
|---|---|
| Настройка Codeception + хелпер Битрикс + конфигурация суит | 1 день |
| Functional-тесты для бизнес-логики (заказы, корзина, расчёты) | 1–3 дня |
| Acceptance-тесты через WebDriver (каталог, чекаут, авторизация) | 2–4 дня |







