Автотесты для конфигурации 1С: с чего начать и чем проверять

· 9 мин

Содержание

Частое заблуждение: тестировать код 1С значит кликать по базе руками после каждой доработки. Так работает, пока в конфигурации десять процедур. Когда их три тысячи, ручная проверка пропускает половину регрессий. Автоматические тесты в 1С писать можно и нужно: есть модульные фреймворки, сценарные тесты на человеческом языке и запуск из командной строки.

Начните с простого. Возьмите одну расчётную функцию, напишите на неё три теста и запустите их одной командой. Остальное (сценарии интерфейса, CI, покрытие) нарастает поверх этого.

Какие бывают тесты: три уровня проверки

Пирамида тестирования в 1С выглядит так же, как в любой другой платформе. Отличается только набор инструментов.

УровеньЧто проверяетЧем пишутСкорость
МодульныйОдну процедуру или функцию в изоляцииxUnit-фреймворки (xUnitFor1C, YAxUnit)Миллисекунды
ИнтеграционныйСвязку модулей, проведение документа, запись в регистрыТе же фреймворки, но с реальными данными в базеСекунды
Сценарный (приёмочный)Работу интерфейса глазами пользователяVanessa Automation, сценарии в GherkinДесятки секунд на сценарий

Правило простое: чем ниже уровень, тем больше тестов и тем они быстрее. Идеальное соотношение для проекта на 1С выглядит как 70% модульных, 20% интеграционных, 10% сценарных. Реальные проекты редко доходят до такой пропорции, но ориентир полезен.

Что тестировать в первую очередь

Не пытайтесь покрыть всё. Выберите места, где ошибка стоит дороже всего:

  • 💰 расчёты: цены, скидки, налоги, зарплатные начисления;
  • 🔁 обмены с внешними системами и разбор входящих файлов;
  • 🧮 общие модули с «чистой» логикой, которые вызываются из десятков мест;
  • 📄 проведение ключевых документов: что записалось в регистры, какие движения получились;
  • 🐛 места, где уже была ошибка. Каждый исправленный баг превращается в тест.

Тестируется хорошо тот код, который не зависит от интерфейса и глобального состояния. Если расчёт сидит внутри обработчика формы, сначала вынесите его в общий модуль. Это полезный рефакторинг и без всяких тестов.

xUnit и Vanessa Automation: чем что писать

Два основных инструмента закрывают разные задачи. Спорить «что лучше» бессмысленно: они дополняют друг друга.

Модульные тесты на xUnit

Фреймворки семейства xUnit запускаются внутри платформы. Вы пишете тестовые процедуры на встроенном языке, а фреймворк находит их, вызывает и собирает отчёт. Самые известные варианты: xUnitFor1C (его ещё называют xddTestRunner) и более новый YAxUnit, который работает с расширениями и удобен для проектов в EDT.

Тест состоит из трёх частей: подготовка данных, вызов проверяемого кода, проверка результата. Пример для функции расчёта скидки:

Процедура ТестДолжен_ПроверитьСкидкуПриБольшомОбъёме() Экспорт

	// Подготовка
	Количество = 100;
	Цена = 500;

	// Вызов
	Сумма = РасчётыСервер.СуммаСоСкидкой(Количество, Цена);

	// Проверка: 100 * 500 = 50 000, скидка 10% -> 45 000
	ЮнитТест.ПроверитьРавенство(Сумма, 45000);

КонецПроцедуры

Точные имена методов утверждений («проверить равенство», «проверить истину» и т.д.) зависят от выбранного фреймворка. Откройте его документацию на GitHub и берите оттуда. Принцип одинаков везде.

Сценарные тесты на Vanessa Automation

Vanessa Automation (в сообществе её зовут «Ванесса») управляет интерфейсом тонкого клиента . Сценарии пишутся на Gherkin: язык близок к обычной речи, поэтому сценарий читает и аналитик, и тестировщик.

Сценарий: Проведение реализации уменьшает остаток на складе
    Дано Я открываю навигационную ссылку "e1cib/list/Документ.РеализацияТоваровУслуг"
    Когда В панели действий я нажимаю на кнопку "Создать"
    И я заполняю шапку документа тестовыми данными
    И в документе я нажимаю на кнопку "Провести и закрыть"
    Тогда остаток товара на складе уменьшился на проданное количество

Каждый шаг сопоставлен со своей программной реализацией. Готовых шагов в библиотеке сотни, недостающие дописывают на встроенном языке.

⚠️ Сценарные тесты хрупкие. Переименовали кнопку, и половина сценариев упала. Не тратьте их на логику, которую можно проверить на нижнем уровне.

Если нужно проверить, как ведёт себя модуль без интерфейса, берите xUnit. Если важна цепочка действий пользователя от открытия формы до результата, берите Vanessa Automation.

Тестовая база и изоляция данных

Главная причина «мигающих» тестов: они зависят от данных, которые кто-то изменил. Тест вчера проходил, сегодня падает, а код не трогали.

Откуда брать данные

Есть три рабочих подхода, и их можно сочетать:

  1. Тест создаёт всё сам. Перед проверкой в базе создаются нужные контрагенты, номенклатура и документы. Надёжно, но медленно, если данных много.
  2. Эталонная база. Заранее подготовленная файловая база с набором данных. Перед прогоном её копируют, после прогона удаляют копию.
  3. Загрузка из выгрузки. Для каждого прогона создаётся пустая база, в неё загружается небольшой .dt-файл с проверенными данными.

Для модульных тестов хватает первого подхода. Для сценарных удобнее второй или третий.

Как не оставлять следы

  • 🧹 Каждый тест убирает за собой: удаляет созданные объекты или откатывает транзакцию.
  • 🔒 Тесты не должны зависеть от порядка запуска. Если тест №5 работает только после №4, он написан неправильно.
  • 🕒 Не используйте текущую дату как вход расчёта. Подставляйте фиксированную, иначе в конце месяца тесты начнут вести себя иначе.
  • 🌐 Внешние сервисы (банк, ЭДО, почта) заменяйте заглушками. Тест не должен ходить в интернет.

Для регистров с итогами и документов с движениями удобно проверять не всю таблицу, а конкретные поля конкретных строк: период, измерения, ресурс. Так тест не ломается из-за посторонних записей.

Типичные ошибки при написании тестов

Эти антипаттерны встречаются чаще остальных.

Тест без проверки. Процедура вызывает код и ничего не утверждает. Она «проходит», даже если код сломан. Каждый тест заканчивается хотя бы одним утверждением.

Один гигантский тест на всё. Когда он падает, непонятно, что именно сломалось. Один тест проверяет одну вещь, и имя говорит какую: ТестДолжен_ВернутьНоль_ЕслиКоличествоПустое.

Проверка реализации, а не результата. Тест лезет внутрь и проверяет, какие промежуточные процедуры были вызваны. После любого рефакторинга он падает без причины. Проверяйте то, что видно снаружи: возвращаемое значение, записанные движения.

Копипаста подготовки данных. В двадцати тестах одинаковые тридцать строк создания контрагента. Вынесите их в общую процедуру-помощник.

Игнор падающих тестов. Красный прогон стал нормой, и на него перестали смотреть. Тест, который падает неделю, чините или удаляйте, но не оставляйте.

Запуск в CI: тесты на каждую правку

Автотесты ценны тогда, когда запускаются сами. Для этого их встраивают в конвейер непрерывной интеграции: Jenkins, GitLab CI, GitHub Actions или любой другой, умеющий выполнять команды.

Из чего состоит прогон

  1. Сервер забирает свежие исходники из репозитория.
  2. Создаётся чистая информационная база и в неё собирается конфигурация из исходников.
  3. Запускается тестовый фреймворк в пакетном режиме.
  4. Результат (успех или падение) возвращается как код выхода и отчёт.
  5. Сборка помечается красной или зелёной, разработчику приходит уведомление.

Платформа умеет всё это из командной строки. Запуск конфигуратора в пакетном режиме выглядит так:

"C:\Program Files\1cv8\<версия>\bin\1cv8.exe" DESIGNER /F "C:\ci\testbase" /DisableStartupDialogs /DisableStartupMessages /LoadConfigFromFiles "C:\repo\src" /UpdateDBCfg /Out "C:\ci\build.log"

Дальше тот же 1cv8 запускается в режиме предприятия с параметром, который передаёт фреймворку путь к настройкам прогона. Точный набор ключей смотрите в документации выбранного фреймворка: у xUnitFor1C, YAxUnit и Vanessa Automation они разные.

⚠️ Не запускайте автотесты на рабочей базе. Конвейер работает только с временными базами, которые создаёт и удаляет сам.

Что учесть на практике

  • Сценарным тестам нужна графическая сессия. На Linux-агентах для этого поднимают виртуальный экран.
  • Лицензии: для тестового клиента нужен свободный сеанс. Продумайте это заранее, иначе прогон повиснет на старте.
  • Быстрые модульные тесты гоняйте на каждый коммит, сценарные тяжёлые прогоняйте ночью или перед релизом.
  • Статический анализ кода подключайте рядом. BSL Language Server с SonarQube ловит неиспользуемые переменные, пустые обработчики и подозрительные запросы до запуска тестов.

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

Покрытие показывает, какие строки кода вообще выполнялись во время прогона. Для 1С его замеряют инструментами вроде Coverage41C: подключаются к отладчику, собирают данные о выполненных строках и формируют отчёт, который понимает SonarQube.

Как читать цифры

Покрытие 80% не означает, что 80% кода проверено. Оно значит только, что 80% строк было выполнено. Тест без утверждений даёт покрытие, но не даёт проверки.

Поэтому смотрите на несколько показателей вместе:

МетрикаЧто говоритНа что обратить внимание
Покрытие строкКакая часть кода выполняласьИщите непокрытые ветки с условиями и обработкой ошибок
Доля падающих тестовЗдоровье набораРост означает нестабильность или реальные регрессии
Время прогонаКак быстро получаете обратную связьЕсли модульные тесты идут дольше 5-10 минут, их перестанут запускать
Замечания статического анализаКачество кода вне тестовСледите за динамикой, а не за абсолютным числом

Какой порог ставить

Для нового кода разумно требовать покрытие 70-80% и не принимать правку, которая его снижает. Для унаследованной конфигурации такой порог нереалистичен: начните с того, что любой исправленный дефект получает тест, а покрытие растёт само.

Не гонитесь за сотней процентов. Тривиальные геттеры и обёртки над платформенными вызовами покрывать смысла нет. Лучше десять сильных тестов на расчёт НДС, чем сотня пустых на каждую форму.

План внедрения: как стартовать за неделю

Внедрять всё сразу не нужно. Рабочая последовательность выглядит так.

  1. День 1-2. Выберите фреймворк и поставьте его в тестовую базу. Запустите демонстрационный тест из поставки. Пока он не зелёный, дальше не идите.
  2. День 3. Выберите пять функций с самыми дорогими последствиями ошибки и напишите по два-три теста на каждую. Обязательно граничные случаи: пустое значение, ноль, отрицательное число, очень большая сумма.
  3. День 4. Напишите скрипт, который собирает базу из исходников и запускает тесты одной командой. Он пригодится и локально, и в конвейере.
  4. День 5. Подключите скрипт к CI на каждый коммит в основную ветку. Договоритесь в команде: красная сборка чинится сегодня.

Дальше правило одно: исправили баг, добавили тест. Через полгода набор вырастет сам, причём вырастет именно там, где код чаще всего ломается.

Готовность тестового контура
Выполнено: 0 / 6

Кто должен писать тесты

Лучше всего, когда тест пишет автор доработки: он знает граничные случаи лучше всех. Сценарные тесты на интерфейс удобно отдавать аналитику или тестировщику, потому что Gherkin читается без знания встроенного языка. Ревью кода включает ревью тестов: если в правке нет теста, проверяющий вправе спросить почему.

Не заставляйте покрывать тестами то, что вот-вот выбросят. Тест на код, который заменят через месяц, обойдётся дороже, чем пользы принесёт.

Частые вопросы

Можно ли тестировать типовую конфигурацию, не меняя её?
Да. Тесты и вспомогательный код выносят в расширение, а проверяемая конфигурация остаётся на поддержке. Расширение подключается только в тестовой базе.
Нужен ли EDT для автотестов?
Нет. Модульные и сценарные тесты работают и из обычного конфигуратора. EDT удобен тем, что исходники лежат в файлах и хорошо ложатся в репозиторий и конвейер.
Сколько времени уходит на первые тесты?
Первый рабочий тест в готовом фреймворке пишется за час-два, если окружение настроено. Основное время уходит на подготовку тестовой базы и данных, а не на сами проверки.
Чем заменить тестирование, если команда маленькая?
Минимальный набор: несколько модульных тестов на самые денежные расчёты плюс один сценарий «открыл, провёл, проверил» на главный документ. Этого уже хватает, чтобы ловить грубые поломки.
Тестируют ли запросы к базе?
Да, как интеграционные тесты: создаёте небольшой набор данных, выполняете запрос и сверяете результат с ожидаемым. Планы запросов и скорость на больших объёмах так не проверить, для этого нужен замер производительности.