Я занимаюсь поддержкой и разработкой технологий для облака 42Clouds. У нас развернуты базы на разделителях, мы используем технологии 1С:Фреш, но немного переделываем их по-своему.
Некоторое время назад мы начитались статей, насмотрелись видео на YouTube и начали активно писать тесты – причем, у нас используются не только сценарные, но и самописные, дымовые тесты.
И в какой-то момент возник вопрос – какого количества тестов достаточно, чтобы наша система была устойчива, в нее можно было легко вносить изменения, не ломая существующую функциональность?
На этот вопрос помогает ответить показатель покрытия кода тестами.
Инструменты, которые отображают покрытие
Что такое покрытие кода и как оно вычисляется? Алгоритмов, чтобы его посчитать, много, мы будем использовать самый простой – покрытие строк.
При расчете покрытия строк кода анализируется исходный код программы.
На слайде вы видите простую функцию.
-
Все строки, которые могут быть выполнены во время теста, помечаются как строки к выполнению – туда не входят комментарии, пустые строки, инструкции препроцессора, директивы компиляции (&НаКлиенте &НаСервере).
-
Весь остальной код помечается как код к покрытию.
-
Далее запускаются тесты, и анализируется, какие же строки были выполнены во время тестов.
-
Результат – процент покрытия, отношение количества строк, которые в ходе тестирования выполнились, к количеству строк, которые должны были выполниться.
Все просто и красиво, но есть проблема. Платформа не предоставляет интерфейс, чтобы посчитать покрытие строк достаточно просто.
Тем не менее, даже в достаточно старых докладах уже встречались варианты, когда покрытие как-то считалось. Но эти механизмы никак не афишировались.
В качестве инструмента для подсчета количества покрытых тестами строк можно использовать SonarQube – здесь на главной странице выводится показатель процента покрытия и множество других метрик кода, которые могут быть подсчитаны благодаря BSL-плагину для SonarQube.
Кроме SonarQube, покрытие можно считать и через другие инструменты – например, через интересный механизм Report Generator, который просто преобразует файл покрытия в HTML-документ, где можно увидеть:
-
что у нас выполнилось, а что – нет;
-
процент по разным модулям;
-
общий процент по проекту.
Например, видно, что некоторые HTTP-сервисы не были покрыты тестами. Хорошо было бы написать тесты, которые проверяют именно их.
Тот же VSCode тоже поддерживает отображение покрытия, для этого есть различные плагины:
-
Coverage-Gutters
-
VSCode LCOV
-
Code Coverage Highlighter
Из всех трех лучше всех работал Coverage-Gutters, он на экране. Отмечает красным, что у нас не выполнилось, зеленым – что выполнилось.
То есть отобразить покрытие мы сможем, осталось его добыть.
Анализ файлов замеров производительности
Самый первый шаг в этом направлении сделан путем выгрузки замеров производительности в файлы и дальнейшей их конвертации.
Для выгрузки замеров производительности в файлы существует инструмент https://github.com/Stepa86/perf-measurements-to-cover, написанный на OneScript.
Он работает хорошо, но требует выполнения большого количества ручных действий в конфигураторе – нужно подключить предметы отладки (HTTP-сервисы, фоновые задания и т.д.), включить замер, запустить тестирование, затем остановить замер и вручную сохранить его данные в файл .pff.
И если в тестируемом решении запускается большое количество фоновых заданий или вызывается HTTP-сервисов – при остановке замера таких окон получится очень много. При этом данные каждого из них нужно сохранять вручную – очень много ручных операций. Посчитать процент можно, но один раз, потом вам это надоест.
Далее появились более продвинутые инструменты, использующие HTTP-отладку, которая появилась в платформе 8.3.7:
Эти инструменты:
-
поднимают прокси-сервер, который перехватывает вызовы от платформы к серверу отладки dbgs.exe;
-
ищут в передаваемых данных информацию о замере производительности и пишут ее на диск,
-
а потом эта информация неким конвертером преобразовывается в один из стандартных форматов покрытия.
Это уже очень крутые инструменты, которые позволяют автоматизировать процесс.
Но при разборе файла покрытия разработчики столкнулись с проблемой так называемого «неизвестного бинаря». Она заключалась в том, что не всегда данные о замерах производительности передавались в текстовом json-формате. Иногда это были бинарные данные, которые расшифровать не получалось – те же фоновые задания в большинстве случаев отправляли данные по замерам производительности в бинарном формате.
Поэтому я решил написать свой инструмент – Coverage41C.
Coverage41C
С инструментом Coverage41C вы можете ознакомиться по адресу https://github.com/proDOOMman/Coverage41C. Он написан на Java, поэтому требует для работы установки JDK 11. В своем составе он использует следующие библиотеки:
-
MDClasses https://github.com/1c-syntax/mdclasses для разбора исходников конфигурации, выгруженной в файлы в формате как EDT, так и конфигуратора.
-
BSL Parser https://github.com/1c-syntax/bsl-parser для анализа исходного кода, вычисления строк покрытия.
-
И некоторые библиотеки, входящие в составе EDT https://edt.1c.ru/. Это самое важное, потому что я обнаружил, что EDT содержит библиотеки, которые позволяют подключаться к серверу отладки dbgs.exe и управлять им – включать замеры, получать данные замеров и их анализировать.
-
И чтобы с моим инструментом было удобнее работать, в него добавлено немного магии.
По поводу библиотек EDT:
EDT – штука проприетарная, поставляется только по подписке, поэтому я не могу распространять библиотеки для работы с сервером отладки в составе программы. Но есть два варианта обхода ограничений.
-
Если у вас стоит EDT на компьютере, то никаких действий выполнять не нужно – через утилиту ring автоматом находится путь к установленной EDT, и библиотеки подключаются. Поэтому если у вас есть установленный EDT – вы просто запускаете замеры покрытия и ни о чем не думаете.
-
Если же вам не хочется тянуть EDT на сервер тестирования – он слишком тяжел для этого, вы хотите держать EDT установленным у себя или вообще против него – вам нужен только конфигуратор. В этом случае, вы можете скопировать из состава EDT в папку библиотеки com._1c.g5.v8.dt.debug.core_*.jar и com._1c.g5.v8.dt.debug.model_*.jar. И установить путь к этой папке в переменную окружения EDT_LOCATION – в этом случае библиотеки также будут подключены и использованы.
Если EDT не установлена или переменная окружения EDT_LOCATION не настроена – при использовании Coverage41C будут выданы ошибки.
HTTP-отладчик платформы 1С
Все видели вкладку «Отладка» в конфигураторе, где есть возможность выбора протокола отладки – HTTP или TCP.
Большинство знакомых разработчиков на вопрос «Что такое отладка по HTTP?» отвечают «Мы не знаем». Но здесь смысл здесь в том, что для EDT нужен отдельный протокол отладки, плюс TCP-протокол отладки был не очень красивым – даже разработчики об этом писали – поэтому появился сервер отладки dbgs, который работал по протоколу HTTP. У отладчика dbgs есть много интересных фишек – например, можно отлаживать одну информационную базу из другой. Но это сейчас не главное.
Многие разработчики путают отладку HTTP-сервисов с HTTP-отладчиком dbgs. Говорят, что отлаживают HTTP-сервис, поэтому, наверняка, включена HTTP-отладка. Но это не совсем так: отладку по HTTP нужно включать отдельно.
Далее немного терминологии.
-
Сервер отладки – это отдельное приложение dbgs.exe, идет в составе платформы.
-
Объект отладки – то, что мы подключаем в конфигураторе: клиентские приложения, серверный контекст, мобильные приложения.
-
Интерфейсы отладки – то, что управляет сервисом отладки: либо конфигуратор, либо EDT, либо моя утилита Coverage 41C.
-
Есть одно ограничение на уровне платформы – одновременно к одной информационной базе может быть подключен только один интерфейс отладки:
-
Если вы запустите конфигуратор и попытаетесь снять замер покрытия – у вас ничего не выйдет, сервер выдаст ошибку.
-
И наоборот: если запущен замер покрытия и вы пытаетесь запустить конфигуратор, чтобы в этот момент что-то отладить, конфигуратор скажет, что информационная база уже отлаживается, и ничего не позволит сделать.
-
Включаем HTTP-отладку
Как же включить HTTP-отладку?
-
Если у вас серверная информационная база – необходимо заглянуть в реестр и к флагу -debug добавить флаг -http. После этого мы перезапускаем агент и HTTP-отладка включается. Не забудьте после этого конфигуратор переключить на режим HTTP-отладки, иначе у вас ничего отлаживаться не будет.
-
Если у вас файловая информационная база. Когда вы хотите отлаживать файловую информационную базу через HTTP в конфигураторе – вы меняете в настройках отладку на HTTP и запускаете приложение. В этот момент конфигуратор сам запускает dbgs.exe и держит его запущенным, пока запущено клиентское приложение.
При запуске Coverage41C мы конфигуратор не используем, поэтому dbgs.exe мы должны запустить вручную – файл dbgs.exe лежит в папке с платформой:
-
в качестве аргумента получает порт, на котором будет запущен (-p 1559).
-
второй вариант запуска – в диапазоне портов в первом свободном порте (-r 1560:1591).
Мы для простоты используем вариант с указанием порта – запускаем dbgs.exe, и он ждет, когда мы подключим клиентское приложение.
Клиентское приложение подключается путем добавления аргументов командной строки. Это наша 1С-ка, которую мы запускаем с флагами:
/debug -http -attach /debuggerURL http://localhost:1550
Чтобы проверить, что сервер отладки действительно запустился – мы адрес отладчика можем открыть в браузере. Он выведет нам, что все работает – it works!
Поддерживаемые форматы
Утилита поддерживает два формата (параметр -f):
-
GenericCoverage – используется для SonarQube
-
Lcov.info – для VSCode, ReportGenerator и т.д., возможности применения такого формата гораздо шире.
Они отличаются: GenericCoverage – xml-формат, Lcov.info – просто текстовый формат.
Тем не менее, SonarQube любим одинэсниками, поэтому по умолчанию покрытие выводится в формате GenericCoverage.
Интерфейс командной строки
Утилита представляет собой консольное приложение. Интерфейс не слишком сложный.
Есть основные команды:
-
start
-
stop
-
chek
-
clean
-
dump
-
stats
-
convert
Для самого простого варианта вам нужна лишь команда start, которая запускает анализ покрытия. На ней мы остановимся подробнее, что вообще с ее помощью можно сделать.
Основные параметры команды start – имя информационной базы и адрес отладчика. По этим параметрам подключается замер покрытия к серверу отладки.
-
Имя информационной базы (параметр -i)
-
Если у вас серверная информационная база – имя информационной базы такое же, как в кластере.
-
Если у вас файловая информационная база, то имя информационной базы будет DefAlias. Можете почитать на ИТС – это имя по умолчанию для любой файловой базы.
-
-
Адрес сервера отладки (параметр -u). В зависимости от типа базы может быть либо http://localhost, либо URL-адрес сервера 1С:Предприятия.
-
Путь к файлу с адресом сервера отладки (параметр -u:file). Существует вариант, когда сервер отладки запускается в диапазоне портов. Тогда он может вписать свой адрес в файл, а мы можем вместо прямой передачи адреса сервера отладки передать путь к файлу, в котором уже записан его адрес. Этот вариант больше нужен для другого режима замеров покрытия, о котором я расскажу в конце доклада.
Мы можем измерять либо покрытие тестами кода конфигурации, либо расширения, либо внешней обработки – что-то одно. Совместные замеры пока не реализованы. Если это кому-то нужно – пишите, что-нибудь придумаем.
-
Если вы хотите замерить покрытие конфигурации – никаких лишних флагов не нужно, измеряется по умолчанию.
-
Если вы хотите померить покрытие расширения, то передается флаг -е и имя расширения, как оно задано в конфигураторе.
-
Если вы хотите измерить покрытие внешней обработки, то флаг -х и путь к epf-файлу внешней обработки в формате file:// и полный путь к файлу. Если где-то ошибетесь – ваше покрытие будет нулевым, потому что файл не найдется в процессе выполнения.
Также нам нужны будут два флага – путь к исходникам конфигурации и путь к директории проекта. Для большинства проектов достаточно задать только путь к исходникам:
-
Путь к исходникам конфигурации (параметр -s). Папка, куда распакована наша конфигурация, наше расширение или внешняя обработка. Для этого параметра поддерживается как формат EDT, так и формат конфигуратора:
-
В случае формата EDT ничего распаковывать не нужно – у нас уже все есть.
-
В случае формата конфигуратора просто выгружаете ваш проект в файлы.
-
-
Путь к директории проекта (параметр -P). Это путь, откуда вы запускаете анализ проекта SonarQube, он может отличаться от пути к исходникам конфигурации. Вещь весьма специфическая, не буду на ней останавливаться.
Остальные параметры:
-
Удаление метаданных на поддержке (флаг -r). Если вы дорабатываете типовую конфигурацию, возможно, вам не имеет смысла мерить покрытие кода, который находится на замке. Тогда вы можете передать флаг --removesupport, указать уровень (NOT_EDITABLE – на замке, EDITABLE_SUPPORT_ENABLED – с возможностью изменения), и такие объекты метаданных не будут анализироваться.
-
Флаг --out – путь к выходному файлу с данными покрытия. Это файл GenericCoverage.xml или Lcov.info, куда будет записана информация. Если вы его забудете передать, информация будет выведена в консоль.
-
Флаг --password – поскольку dbgs.exe может быть опубликован где-нибудь в интернете, предполагается, что его нужно защищать паролем. Поэтому если dbgs.exe у вас запущен с паролем, то для подключения к нему вам нужно передать этот самый пароль. Причем пароль вводится в интерактивном режиме – при запуске будет запрос «Введите пароль», и вы должны вбить его ручками.
-
Для того, чтобы передавать пароль в режиме pipeline существует еще один аргумент командной строки -p:env, где указывается переменная окружения, в которой записан пароль.
-
И последний аргумент --opid – идентификатор родительского процесса – нужен, чтобы дождаться завершения работы программы, которая выполняет тесты, и завершить замеры покрытия. Например, вы запустили менеджер тестирования, передали его идентификатор в утилиту – после завершения теста, когда менеджер тестирования закрылся, программа завершает замеры покрытия и сохраняет все на диск.
Примеры использования команды start.
-
Измерение покрытия кода для конфигурации в файловой базе:
Coverage41C start -i DefAlias -u http://127.0.0.1:1550 -s D:\Sources -o genericCoverage.xml
-
Измерение покрытия кода конфигурации в серверной базе с вырезанием кода на замке – имя конфигурации меняется, меняется адрес отладчика, и добавляется, что мы вырезаем код на замке:
Coverage41C start -i IBName -u http://server1c:1550 -s D:\Sources -o genericCoverage.xml -r NOT_EDITABLE
-
Покрытие для кода расширения – добавляется имя расширения:
Coverage41C start -e ExtensionName -i DefAlias -u http://127.0.0.1:1550 -s D:\Sources -o genericCoverage.xml
-
Покрытие для кода внешней обработки.
Coverage41C start -x file://D:/Infostart.epf -s D:\Sources\External.mdo -o genericCoverage.xml
Причем с внешними обработками есть особенность: помните, что в параметр -x передается путь к epf-ке в формате uri, а в параметр -s или -P передается не путь к директории, куда распакованы исходники, а путь к корневой xml-ке или к корневому файлу mdo. Он имеет то же наименование, что и наименование вашей внешней обработки.
Далее команды stop, dump, clean.
-
Stop – останавливает замеры покрытия кода и записывает файл на диск.
-
Dump пишет текущее состояние на диск.
-
Clean очищает информацию о выполненных строках кода в запущенном экземпляре программы.
Эти команды принимают аргументы: имя информационной базы и имя отладчика. По связке этих двух параметров ищется экземпляр Coverage41C, в который передаются эти команды.
Также команда stop нужна для пайплайнов или скриптов – если хотите прервать команду start, запущенную в консоли, вручную, просто нажмите Ctrl+C. Тогда будет корректное завершение с записью всей информации на диск.
Есть еще команда convert – некоторые по привычке пытаются ее использовать всегда, это уже замечено на GitHub в сообщениях об ошибках.
Суть в том, что все предыдущие инструменты требовали конвертации данных: сначала шел сбор данных, затем – конвертация. Здесь, если мы передали путь к исходникам, конвертация не нужна – на выходе мы получаем файл нужного формата, который можно использовать.
Но если на сервере, где вы проводите тесты, нет исходников – допустим, их неудобно туда тащить – тогда вы команде start не передаете путь к исходникам, и данные в выходном файле будут записаны во внутреннем формате, где вместо путей к файлам указаны идентификаторы метаданных. Такой файл вы можете передать обратно – на компьютер, где распакованы исходники вашего проекта, и сконвертировать его в нужный вам формат с помощью команды convert.
У команды convert есть:
-
флаг -с – в него передается файл с сырыми данными покрытия (то, что получилось на выходе после сбора покрытия кода);
-
с помощью флага -r также можно удалять код на поддержке;
-
все остальное – путь к исходникам (флаг -s), путь к проекту (флаг -P) и выходной файл (флаг -o) – про них мы уже говорили.
Интеграция с Vanessa-ADD/Vanessa-automation
Возможно, кто-то скажет, что работать с программой через консоль сложно и непонятно, лучше сделать проще: например, написать графический интерфейс. Не надо этого делать.
Если вы используете BDD-тестирование – Vanessa-ADD или Vanessa-automation – вы можете скачать библиотеку шагов, которая находится в дебрях моего репозитория по ссылке https://github.com/proDOOMman/Coverage41C/blob/master/src/test/resources/bdd/features/step_definitions/Coverage41C.epf.
Эту обработку нужно положить в папку step_definitions каталога с вашими фичами или каталога библиотек Vanessa, и после обновления кэша шагов у вас появятся готовые шаги.
В принципе, библиотека шагов повторяет весь консольный интерфейс программы, но дополнительно есть несколько полезностей.
Например, вы можете прямо из кода Gherkin запускать сервер отладки – для этого есть два шага: «И я запускаю сервер отладки» или «И я запускаю сервер отладки в диапазоне портов». На файловых базах я рекомендую вам использовать второй шаг с указанием, на каких портах вы можете запустить dbgs.
При запуске любого из этих шагов будет запущен dbgs.exe, в котором будет указано: работать столько же, сколько жив менеджер тестирования. Полный адрес сервера отладки (URL с портом) будет записан в настройке запуска клиентов тестирования. В целом, это все, что нам нужно, чтобы в дальнейшем клиент тестирования подключился к этому серверу отладки, и можно было снимать замеры.
Для установки Coverage41C есть три варианта:
-
Либо вы просто скачиваете с GitHub последний релиз и его распаковываете – это обычный zip-архив.
-
Либо используете пакетный менеджер Chocolatey с командой «choco install Coverage41C». Но там, возможно, не всегда будут актуальные версии, потому что модерация на Chocolatey очень длительная.
-
И третий вариант – использовать шаг «И я устанавливаю Coverage41C». В этом случае также с GitHub скачивается последняя версия и устанавливается в каталог проекта.
У библиотеки шагов те же возможности, что и в консольной утилите. Например, есть шаг «И я устанавливаю имя ИБ для анализа покрытия» и другие.
Имя информационной базы также вычисляется автоматически при шаге «И я настраиваю отладку клиента тестирования» или «И я запускаю сервер отладки» – любой из этих шагов автоматически определяет имя текущей информационной базы и автоматически заносит его в настройки Coverage41C.
Для того, чтобы запустить замер покрытия с помощью библиотеки шагов Gherkin, вам нужно всего лишь пять шагов:
-
И я запускаю сервер отладки
-
И я устанавливаю Coverage41C;
-
И я устанавливаю путь к проекту для анализа покрытия (или «И я устанавливаю путь к исходникам для анализа покрытия»)
-
И я устанавливаю имя выходного файла анализа покрытия
-
И я запускаю анализ покрытия.
Анализ покрытия завершится автоматически после закрытия менеджера тестирования.
Если вы для запуска тестирования используете тот же Vanessa-runner – он автоматом может закрывать менеджер тестирования. После этого замеры завершаются, сохраняются на диск, и после этого вы можете их использовать.
Возможна небольшая пауза, потому что запись на диск займет какое-то время, особенно на больших проектах.
Работа Coverage41C в режиме реального времени
У меня есть маленькая база, на которой я покажу, как можно организовать BDD-тестирование с покрытием, используя предложенную библиотеку шагов.
Итак, у меня есть:
-
папка с файловой информационной базой – база очень простая и содержит только одну обработку, которую мы и будем тестировать;
-
папка с ее распакованными исходниками;
-
и папка, где лежит фича и рядом с ней в подпапке step_definitions находится библиотека шагов Coverage41C.epf.
Vanessa запустилась, нажимаем «Выполнить сценарий». Запускается клиент тестирования – сейчас будет запущена наша обработка, которая выведет «Привет, Infostart». В коде обработки есть одно условие, которое в зависимости от входных параметров пойдет либо по одной ветке, либо по другой.
Итак, тестирование закончено, все закрываем и смотрим папку с исходниками.
В результате тестирования в папке с исходниками появился файл genericCoverage.xml.
В нем у нас указаны строки покрытия – видно, что есть три строки, из которых две были выполнены.
Исходники с данными покрытия мы можем передать в SonarQube, у меня для этого есть специальный bat-файл, в котором вызывается sonar-scanner.bat с ключами -Dsonar.projectBaseDir и -Dsonar.coverageReportPaths – подробнее о том, как загружать исходники в SonarQube вы можете прочитать в документации.
Запускаем сканирование проекта и посмотрим на результат. Итак, покрытие 66,7%.
Вот так выглядит покрытие – зеленым покрытые, а красным – непокрытые строки.
На этом прощаюсь: заходите на GitHub https://github.com/proDOOMman/Coverage41C, оставляйте сообщения об ошибках и пожелания – все учтем. Спасибо за внимание.
*************
Данная статья написана по итогам доклада (видео), прочитанного на онлайн-митапе "DevOps в 1С: Тестирование и контроль качества решений на 1С".