Магазин на 1С-Битрикс — это десятки связанных механизмов: каталог с фильтром, корзина с расчётом скидок, оформление заказа, платёжный шлюз, обмен с 1С. Меняете одну мелочь в шаблоне корзины — и незаметно ломается купон или переход к оплате. Ручная проверка всего этого перед каждым релизом съедает часы, а под конец спринта её всё равно делают «по диагонали». Итог знаком многим: сломанная оплата обнаруживается уже на живых заказах.
Автотесты закрывают именно эту дыру. Ниже — как покрыть ключевые сценарии магазина (каталог, корзина, оплата) автотестами на Playwright и проверками через API, как готовить тестовые данные, бороться с «мигающими» тестами и встроить всё в CI, чтобы деплой не уходил на прод со сломанной витриной. Это выжимка из наших проектов по разработке на 1С-Битрикс — с конкретными сценариями, а не общими словами про «важность тестирования».
Коротко
- Критичный путь покупателя (каталог → корзина → оплата) покрывайте E2E-тестами Playwright, бизнес-логику — быстрыми API-тестами.
- Оплату тестируйте в sandbox-режиме шлюза и по колбэкам, не проводя реальных платежей.
- Тестовые данные создавайте фикстурами на staging, изолируйте на каждый тест и удаляйте после прогона.
- Опирайтесь на стабильные
data-testid, а не на классы вёрстки — это лечит половину флаки. - Встройте автотесты в CI как ворота: smoke на каждый коммит, полный регресс перед релизом.
Зачем магазину на Битрикс автотесты
Интернет-магазин зарабатывает на одном непрерывном сценарии: покупатель нашёл товар, положил в корзину, оформил и оплатил заказ. Если хоть один шаг этой цепочки сломан, магазин теряет деньги напрямую — и часто молча, потому что пользователь просто уходит, а не пишет в поддержку. Автотесты нужны, чтобы этот критичный путь проверялся автоматически и на каждое изменение, а не раз в квартал силами уставшего тестировщика.
На платформе 1С-Битрикс поводов для регресса особенно много. Обновляется ядро или маркетплейс-модуль, приезжает новый обмен с 1С, дизайнер правит шаблон компонента корзины, маркетолог включает новую акцию — каждое из этих действий может задеть оформление заказа. Ручной регресс всего этого нереалистичен: комбинаций слишком много. Автотесты берут на себя рутину и освобождают людей для исследовательского тестирования, где машина бесполезна.
Важно правильно понимать цель. Автотесты не заменяют ручное и приёмочное тестирование, а дополняют их — про полную картину QA магазина мы писали в отдельном материале про тестирование и QA интернет-магазина на 1С-Битрикс. Задача автотестов — быстро и надёжно ловить регресс в тех местах, где цена ошибки высока, а сценарий стабилен и повторяем. Это ровно каталог, корзина и оплата.
Ещё один эффект, который недооценивают, — автотесты фиксируют ожидаемое поведение. Когда сценарий оформления заказа описан кодом, он превращается в живую документацию: новый разработчик открывает тест и видит, как именно должна работать корзина, какие поля обязательны, какой статус получает заказ. Это ускоряет ввод людей в проект и снижает число «а я не знал, что так нельзя».
Пирамида тестов: где браузер, где API
Прежде чем писать первый тест, полезно договориться, что именно проверять на каждом уровне. Классическая пирамида тестирования подсказывает: чем ниже уровень, тем тесты дешевле, быстрее и стабильнее, поэтому их должно быть больше. Для магазина на Битрикс это раскладывается так.
- API-тесты (широкое основание). Проверяют бизнес-логику без браузера: расчёт корзины, применение скидки, доступность товара, смену статуса заказа. Работают за десятки миллисекунд, почти не «мигают», их можно и нужно иметь много.
- Интеграционные проверки (середина). Связка «компонент + база + обмен»: корректно ли компонент корзины отдаёт итог, правильно ли отрабатывает событие оформления заказа. Здесь удобно смешивать вызовы API и точечную проверку страниц.
- E2E-тесты Playwright (узкая вершина). Гоняют настоящий браузер по пути покупателя. Самые ценные, но самые медленные и хрупкие — поэтому их держат немного и только на критичных сценариях.
Главная ошибка новичков — перевернуть пирамиду и всё проверять через браузер. Такой набор тестов долго идёт, часто «мигает» и его быстро перестают чинить. Правильный подход: логику отжимаем вниз, в быстрые API-тесты, а через браузер прогоняем только то, что реально видит и делает клиент. Тогда набор остаётся быстрым и ему продолжают доверять.
Стек: Playwright, API и окружение
Соберём минимальный, но полноценный стек для автотестов магазина. Ничего экзотического — всё ставится штатными средствами и живёт в отдельном каталоге репозитория, не мешая коду сайта.
| Слой | Инструмент | За что отвечает |
|---|---|---|
| E2E-браузер | Playwright Test | Прогон сценариев в Chromium/Firefox/WebKit, ожидания, трейсы |
| API-проверки | request-контекст Playwright | REST-запросы к Битриксу без браузера, проверка ответов |
| Данные | Fixtures + seed-скрипт | Создание товаров, разделов и пользователей перед прогоном |
| Оплата | Sandbox платёжного шлюза | Тестовые карты, success/fail-URL, колбэки без реальных списаний |
| Окружение | Staging-копия сайта | Изолированная площадка с тестовой базой, не прод |
| Запуск | CI (GitLab CI / GitHub Actions) | Автозапуск на коммит и перед деплоем, отчёты и артефакты |
Ключевая мысль: и E2E, и API-тесты можно писать в одном инструменте. Playwright умеет не только водить браузер, но и делать «чистые» HTTP-запросы через request-контекст. Это удобно: один синтаксис, один раннер, один отчёт, а тесты разных уровней лежат рядом. Стартовый конфиг проекта минимален:
// playwright.config.ts
import { defineConfig } from '@playwright/test';
export default defineConfig({
testDir: './tests',
timeout: 30_000,
retries: process.env.CI ? 1 : 0,
use: {
baseURL: process.env.BASE_URL, // https://staging.shop.ru
trace: 'on-first-retry', // трейс только при повторе
screenshot: 'only-on-failure',
},
reporter: [['list'], ['html', { open: 'never' }]],
});
Обратите внимание на baseURL из переменной окружения — тесты не должны знать конкретный адрес, чтобы одинаково гоняться и локально, и на staging в CI. О том, как поднять и поддерживать такую площадку, есть отдельный разбор про staging-окружение и деплой магазина на Битрикс.
Ключевые сценарии: каталог, корзина, оплата
Не пытайтесь покрыть всё сразу. Есть три группы сценариев, которые дают максимум пользы на единицу усилий, — именно с них начинают. Ниже — карта того, что стоит автоматизировать в первую очередь.
| Область | Сценарий | Уровень теста |
|---|---|---|
| Каталог | Открытие раздела, поиск, работа фильтра | E2E + API |
| Каталог | Карточка товара: цена, наличие, выбор SKU | E2E |
| Корзина | Добавление, изменение количества, удаление | E2E + API |
| Корзина | Скидка, купон, пересчёт итога | API |
| Оформление | Ввод данных, выбор доставки и оплаты | E2E |
| Оплата | Переход на шлюз, success/fail, статус заказа | E2E + API |
Логика распределения простая. Всё, что покупатель видит и щёлкает мышью, проходит через браузер, потому что тут важна именно верстка и клиентские скрипты. Всё, что считается на бэкенде (итог корзины, применение купона, статус заказа), быстрее и надёжнее проверять запросом к API. Многие сценарии удобно проверять на обоих уровнях: E2E убеждается, что кнопка работает, а API — что за кнопкой посчиталось правильное число.
Автотесты каталога и фильтра
Каталог — вход в магазин, и его поломки видны сразу всем посетителям. Здесь автотесты проверяют, что раздел открывается, товары выводятся, поиск и умный фильтр отдают релевантную выдачу. На большом каталоге особенно важен фильтр: он завязан на фасетный индекс и легко ломается после обмена с 1С или переиндексации.
Базовый E2E-сценарий фильтра выглядит так: открыть раздел, применить значение фильтра, дождаться обновления списка и проверить, что все карточки соответствуют условию. Ключевой момент — не ставить фиксированную паузу, а ждать именно реакцию интерфейса. Playwright это делает сам:
test('фильтр по бренду сужает выдачу', async ({ page }) => {
await page.goto('/catalog/smartfony/');
await page.getByTestId('filter-brand-apple').check();
// ждём обновления списка, а не sleep
await expect(page.getByTestId('product-card')).not.toHaveCount(0);
const brands = page.getByTestId('card-brand');
for (const b of await brands.allInnerTexts()) {
expect(b).toContain('Apple');
}
});
Что ещё стоит покрыть в каталоге:
- Пустая выдача. Фильтр без результатов должен показывать корректную заглушку, а не битую страницу.
- Счётчики фильтра. Число рядом со значением совпадает с реальным количеством найденных товаров.
- Пагинация и сортировка. Переход по страницам сохраняет выбранный фильтр, сортировка меняет порядок.
- Наличие и цена в карточке. Для товара «нет в наличии» кнопка «Купить» неактивна или заменена на «Уведомить».
Быстрее всего часть этих проверок делать через API: запрос к списку товаров раздела с параметром фильтра возвращает JSON, в котором легко проверить и количество, и состав, не поднимая браузер. Браузерный тест оставьте для проверки самой вёрстки и клиентского поведения фильтра.
Автотесты корзины и оформления
Корзина — самое «расчётное» место магазина, и именно здесь чаще всего прячутся дорогие ошибки: неверный итог, задвоение товара, слетевшая скидка. Автотесты корзины делятся на две части: браузерные проверяют поведение и вёрстку, API-тесты — арифметику.
Браузерный сценарий проходит путь покупателя: добавить товар, изменить количество, увидеть пересчёт итога, перейти к оформлению. Проверяют не только «кнопка нажалась», но и что число в шапке-счётчике и сумма обновились корректно.
test('корзина пересчитывает итог при +1 к количеству', async ({ page }) => {
await page.goto('/catalog/smartfony/iphone-15/');
await page.getByTestId('add-to-cart').click();
await page.goto('/personal/cart/');
await page.getByTestId('qty-plus').click();
await expect(page.getByTestId('cart-qty')).toHaveText('2');
await expect(page.getByTestId('cart-total')).not.toHaveText('0 ₽');
});
Оформление заказа — отдельный критичный сценарий. Здесь тест заполняет контактные данные, выбирает способ доставки и оплаты, подтверждает заказ и проверяет, что заказ создан и получил корректный статус. Важно гонять этот сценарий и для гостя, и для авторизованного пользователя — логика полей и предзаполнения у них разная.
Автотесты оплаты в sandbox
Оплата пугает автоматизаторов больше всего: «как тестировать деньги?». Ответ — в тестовом режиме шлюза. Все крупные провайдеры (ЮKassa, Сбербанк, Тинькофф, PayKeeper) дают sandbox с тестовыми картами, которые имитируют успех, отказ и таймаут, не списывая реальных средств. Задача автотеста — проверить не сам банк, а корректность интеграции магазина со шлюзом.
Сквозной сценарий оплаты состоит из трёх проверяемых точек:
- Переход на шлюз. После оформления заказа пользователь корректно уходит на страницу оплаты с правильной суммой и номером заказа.
- Возврат по результату. Тестовая «успешная» карта возвращает покупателя на success-URL, «отклонённая» — на fail-URL с понятным сообщением.
- Смена статуса заказа. После успешного колбэка (webhook) от шлюза заказ в Битриксе переходит в статус «оплачен». Это ключевая проверка — именно тут ломается интеграция.
Колбэк оплаты приходит от шлюза на серверный обработчик, а не в браузер, поэтому его удобно проверять API-запросом: имитируем уведомление платёжной системы и убеждаемся, что заказ сменил статус. Так тест не зависит от того, успел ли sandbox прислать колбэк во время браузерного прогона.
Проверки через REST API Битрикса
API-тесты — это дешёвая и быстрая половина покрытия. Вместо того чтобы кликать по интерфейсу, тест обращается к серверу напрямую и проверяет ответ. В 1С-Битрикс для этого есть штатный REST (модуль rest, вебхуки и OAuth-приложения), а для магазина — методы каталога, корзины и заказов. Плюс к этому удобно поднять собственный лёгкий endpoint под тестовые нужды: создать товар, очистить корзину, получить статус заказа.
Playwright делает такие запросы без браузера — через request-контекст. Это тот же тест-раннер и тот же отчёт, что для E2E:
test('API: применение купона снижает итог', async ({ request }) => {
// добавляем товар в корзину тестового пользователя
await request.post('/api/test/cart/add', {
data: { productId: 101, quantity: 1 },
});
const before = await (await request.get('/api/test/cart')).json();
// применяем купон
await request.post('/api/test/cart/coupon', { data: { code: 'TEST10' } });
const after = await (await request.get('/api/test/cart')).json();
expect(after.total).toBeLessThan(before.total);
expect(after.discount).toBeGreaterThan(0);
});
Что особенно удобно проверять через API:
- Расчёт корзины. Сумма, скидки, купоны, доставка — вся арифметика без вёрстки.
- Статусы заказа. Переходы «новый → оплачен → в доставке» и права на смену статуса.
- Доступность товара. Остатки, скрытие из выдачи, цены для разных групп покупателей.
- Обмен с 1С. После имитации импорта проверить, что товар появился, а цена обновилась.
API-тесты не только быстрее браузерных на порядок — они ещё и стабильнее, потому что не зависят от вёрстки и клиентских скриптов. Держите на этом уровне максимум бизнес-логики: набор останется быстрым, а E2E возьмёт на себя только то, что действительно требует настоящего браузера.
Тестовые данные и фикстуры
Автотесты магазина падают чаще всего не из-за бага в коде, а из-за данных. Кто-то поменял цену товара, на который завязан тест; обмен с 1С убрал позицию с витрины; предыдущий прогон оставил «грязную» корзину. Лечится это одним принципом: каждый тест сам создаёт нужные данные и сам за собой убирает, а гоняется всё на изолированном окружении, а не на проде.
Практическая схема работы с данными:
- Seed перед прогоном. Скрипт создаёт эталонные раздел, товар и тестового пользователя через REST API. Тесты знают их идентификаторы и не зависят от того, что лежит в боевом каталоге.
- Изоляция на тест. Каждый сценарий работает со своим набором: своя корзина, свой заказ. Общие данные между тестами — источник гонок и флаки.
- Очистка после. В teardown тест удаляет созданные заказы и очищает корзину. База не распухает «мусором» от прогонов.
- Отдельная тестовая база. Прогоны идут на staging с копией структуры, но с синтетическими данными — реальные заказы клиентов там не появляются.
Фикстуры Playwright удобно оформить так, чтобы тест получал готовое окружение и не думал о подготовке:
// fixtures.ts — тестовый заказ создаётся и удаляется автоматически
import { test as base } from '@playwright/test';
export const test = base.extend<{ order: { id: number } }>({
order: async ({ request }, use) => {
const res = await request.post('/api/test/order', {
data: { productId: 101, quantity: 1 },
});
const order = await res.json();
await use(order); // отдаём тесту
await request.delete(`/api/test/order/${order.id}`); // убираем за собой
},
});
Такой подход делает тесты повторяемыми: их можно запускать в любом порядке, параллельно и много раз подряд — результат не меняется. Именно повторяемость отличает набор, которому доверяют, от набора, который «иногда красный, но это, наверное, ничего».
Стабильные селекторы и data-атрибуты
Отдельная и очень частая причина хрупких тестов — привязка к вёрстке. Если тест ищет кнопку по классу .btn-primary.js-buy, он сломается, как только дизайнер переименует класс или поменяет структуру блока. А в магазине вёрстку правят постоянно. Решение — договориться о стабильных атрибутах для автотестов.
Заведите атрибут data-testid (или другой согласованный) на ключевых элементах: кнопка «Купить», счётчик корзины, поле итога, элементы фильтра. Эти атрибуты существуют только для тестов и не меняются при рестайлинге. Playwright их прекрасно понимает:
<!-- в шаблоне компонента корзины -->
<button data-testid="add-to-cart" class="btn btn-primary">Купить</button>
<span data-testid="cart-total"><?= $total ?> ₽</span>
// в тесте — привязка к смыслу, а не к оформлению
await page.getByTestId('add-to-cart').click();
await expect(page.getByTestId('cart-total')).toBeVisible();
Правила хорошего тона по селекторам:
- Смысл, а не оформление. Селектор описывает роль элемента (кнопка покупки), а не его вид (синяя кнопка).
- Роли и текст — тоже опора.
getByRoleиgetByTextустойчивы и заодно проверяют доступность интерфейса. - Никаких длинных CSS-цепочек. Селектор из пяти вложенных классов сломается от любой правки вёрстки.
- Атрибуты в шаблонах компонентов. Проставляйте
data-testidв шаблонах Битрикса один раз — и все тесты становятся устойчивее.
Реализация в 1С-Битрикс
Теперь конкретика по платформе: что и где настраивать, чтобы автотесты завелись на магазине именно 1С-Битрикс. Ничего в ядре менять не нужно — работаем штатными механизмами.
- Включите модуль REST. В «Marketplace → Установленные решения» и «Настройки → REST API» активируйте модуль
rest. Для серверных проверок заведите входящий вебхук с правами на каталог, корзину и заказы (catalog,sale). - Заведите тестовые endpoint'ы. Небольшой обработчик (например, в
/api/test/) с методами создать/очистить корзину, создать/удалить заказ, получить статус. Он живёт только на staging и закрыт токеном — через него фикстуры готовят данные. - Проставьте data-атрибуты в шаблонах. В кастомизированных шаблонах компонентов
sale.basket.basket,catalog.sectionи оформления заказа добавьтеdata-testidна ключевые элементы. Это разовая правка, которая стабилизирует все E2E-тесты. - Настройте sandbox платёжной системы. В «Магазин → Настройки → Платёжные системы» заведите тестовый режим шлюза с тестовыми ключами. Пропишите отдельные success/fail-URL для тестового окружения.
- Разверните staging. Копия сайта с тестовой базой и синтетическими данными, куда деплоятся изменения перед продом. Именно на ней CI гоняет автотесты.
Схематично тестовый обработчик и настройки платёжки в админке выглядят так:
Встраивание в CI/CD
Автотесты приносят пользу, только когда запускаются автоматически. Тесты, которые «гоняет кто-то иногда руками», быстро устаревают и перестают отражать реальность. Поэтому их встраивают в конвейер CI/CD как обязательный этап между сборкой и деплоем. Подробно про сам конвейер для платформы мы писали в материале про CI/CD и деплой для 1С-Битрикс — здесь сосредоточимся на месте автотестов в нём.
Разумная стратегия запуска делит тесты по скорости и важности:
| Набор | Когда запускать | Что входит |
|---|---|---|
| Smoke + API | На каждый коммит / pull request | Золотой путь, ключевые API-проверки — минуты |
| Регресс E2E | Перед деплоем на прод | Все критичные браузерные сценарии |
| Полный ночной | По расписанию ночью | Расширенное покрытие, кросс-браузерность |
Ключевая идея — тесты становятся воротами: не прошёл smoke — pull request не мёржится; упал регресс — деплой на прод не уходит. Так сломанная оплата ловится в конвейере, а не на живых заказах. Минимальный job для GitHub Actions:
# .github/workflows/e2e.yml
name: e2e
on: [push]
jobs:
playwright:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with: { node-version: 20 }
- run: npm ci
- run: npx playwright install --with-deps chromium
- run: npx playwright test
env:
BASE_URL: ${{ secrets.STAGING_URL }}
- uses: actions/upload-artifact@v4
if: failure()
with: { name: playwright-report, path: playwright-report/ }
Обратите внимание на две детали. Во-первых, адрес staging и платёжные ключи приходят из секретов CI, а не лежат в коде. Во-вторых, при падении в артефакты выгружается HTML-отчёт с трейсами и скриншотами — по нему падение разбирают, не воспроизводя вручную. Это резко ускоряет починку красных прогонов.
Борьба с флаки-тестами
Флаки-тест — тот, что при неизменном коде то падает, то проходит. Это худшее, что может случиться с набором: красным прогонам перестают верить, начинают перезапускать «на всякий случай», и в какой-то момент пропускают настоящий баг. Поэтому нестабильные тесты чинят немедленно, а не терпят. Основные причины флаки и как их лечить:
- Фиксированные паузы.
waitForTimeout(2000)— источник флаки номер один. Заменяйте на ожидание конкретного условия: видимости элемента, появления текста, завершения запроса. Playwright ждёт сам. - Общие данные между тестами. Если два теста работают с одной корзиной, порядок и параллельность ломают их. Изолируйте данные на каждый тест.
- Гонки с обменом 1С. Импорт может менять каталог во время прогона. Тестовые товары должны быть вне обмена или обмен на staging отключён на время тестов.
- Хрупкие селекторы. Привязка к вёрстке ломается от правок дизайна. Переходите на
data-testidи роли. - Внешние сервисы. Реальный платёжный шлюз или сторонний виджет иногда недоступны. Мокайте внешнее, используйте sandbox, а точечный retry оставляйте только для по-настоящему сетевых шагов.
Полезная практика — карантин. Тест, который начал мигать, временно помечают и уводят из блокирующего набора, но заводят задачу на починку с дедлайном. Так красный «шум» не блокирует команду, но и нестабильный тест не забывается навсегда. Ключевое правило: карантин — это временно, а не кладбище тестов.
Частые ошибки
- Перевернули пирамиду и всё гоняют через браузер — набор медленный, «мигает» и его перестают чинить.
- Тестируют на боевой базе — прогоны оставляют мусорные заказы, а падения зависят от того, что кто-то поменял на проде.
- Привязывают селекторы к классам вёрстки — тесты рушатся от любого рестайлинга шаблона.
- Ставят
sleepвместо ожиданий Playwright — тесты то проходят, то падают на медленных страницах. - Проверяют оплату на реальном шлюзе — списывают деньги и зависят от доступности боевого банка.
- Не изолируют данные — тесты делят корзину и заказы, порядок и параллельность ломают прогон.
- Терпят флаки-тесты «потом починим» — красным прогонам перестают верить и пропускают настоящий баг.
- Хранят секреты и токены прямо в репозитории вместо секретов CI — прямая утечка доступов.
Чек-лист внедрения
Сведём всё в практический список, по которому удобно оценивать готовность автотестов магазина.
- Определён критичный путь. Золотой сценарий «каталог → корзина → оплата» описан и покрыт сквозным E2E-тестом в первую очередь.
- Разделены уровни. Бизнес-логика ушла в быстрые API-тесты, браузер оставлен для того, что видит покупатель.
- Оплата в sandbox. Платёжные сценарии гоняются в тестовом режиме шлюза, статус заказа проверяется по колбэку.
- Данные изолированы. Фикстуры создают и удаляют тестовые товары, заказы и пользователей; прогоны идут на staging.
- Селекторы стабильны. Ключевые элементы помечены
data-testid, тесты не завязаны на классы вёрстки. - Секреты вынесены. Адрес staging и платёжные ключи лежат в секретах CI, а не в коде.
- Тесты в CI как ворота. Smoke на каждый коммит, регресс перед деплоем; красный прогон блокирует выкладку.
- Флаки под контролем. Нестабильные тесты чинятся или уходят в карантин с задачей, а не терпятся молча.
Вывод
Автотесты для магазина на 1С-Битрикс — это не про «покрыть всё», а про надёжную защиту денежного пути покупателя. Покройте каталог, корзину и оплату сквозными сценариями Playwright, отожмите бизнес-логику в быстрые API-тесты, готовьте данные фикстурами на staging и встройте набор в CI как ворота деплоя. Тогда сломанная оплата будет всплывать в конвейере за минуты, а не на живых заказах спустя сутки — и релизы перестанут быть лотереей.