Отслеживаем успехи верификации в Obsidian
- Главный вопрос жизни, Вселенной и всего такого
- Контроль хода верификации
- Обсидиан следящий
- Бонус: покрытие чекеров
- Заключение
Главный вопрос жизни, Вселенной и всего такого
"Мы уже приехали?" -- так можно сформулировать главный вопрос верификации. И позвольте вас остановить, прежде чем вы неразборчиво пробурчите что-то про функциональное и кодовое покрытие. Это лишь один элемент мозаики. Глядя в отчёт покрытия, нельзя сделать никаких выводов о покрытии требований.
А как их покрыть? Написать тесты для этого функционала, группы покрытия и чекеры.
Когда требование считается покрытым? Когда его тесты проходят, группы закрываются, чекеры работают.
Как отследить прогресс от беспорядочной кучи до стройного списка полностью покрытых требований? А вот здесь уже всё не так однозначно.
Контроль хода верификации
Существует множество способов для отслеживания хода верификации, от ручного заполнения таблиц в Excel до решений вроде vManager, которые обещают позаботиться обо всех ваших потребностях (сдерживают ли они обещание, другой вопрос). Я не буду начинать холивар на эту тему и предложу новую концепцию. Просто потому что могу.
Моё решение:
- Бесплатное.
- Лёгкое в установке.
- Позволяет совместную работу.
- Позволяет расширение скриптами.
- Не вызывает попаболи (я надеюсь).
- Кроссплатформенное.
- Было собрано на коленке за два вечера, поэтому не ждите чудес.
Обсидиан следящий
Обзор фич
Узрите, Obsidian, приложение для создания заметок в формате Markdown, молоток с возможностью расширения до микроскопа.
Для примера, рассмотрим верификацию котика. Всё верно, котика.
Таблицу на изображении ниже я буду называть привычным для меня термином VPTD, Verification Progress Tracking Document. В ней перечислены все требования и чем и как они покрыты.
Всё красным шрифтов это ссылка на другую страницу. Таблица формируется автоматически, а связь между требованиями, тестами и группами указывается на странице описания требования. Страницы тестов и групп содержат информацию о своём состоянии.
По этой таблице легко заметно, что у нас нет ни одного полностью покрытого требования, два не имеют связанных групп, а одно -- даже тестов.
Для упрощения поиска проблемных мест есть страница Dashboard.
В первом списке отображаются требования без связанного теста или группы. Второй список показывает требования, у которых тесты есть, но не все из них проходят. Таблица приводит все падающие тесты и их ошибки. Последний список собирает все todo из всех тестов.
Реализация
Страницы в Obsidian это Markdown файлы, хранящиеся локально на комьютере. С одной стороны отсутствие необходимости стучаться на сервер упрощает скриптовую обработку, с другой - позволяет самим выбрать способ общего доступа, будь то сетевой диск, облачное хранилище вроде Dropbox или система контроля версий.
Требования
Посмотрим как выглядит страница требования на примере "Jump vertically from standing position".
|
Всё, что она содержит, это ссылки на тесты и группы. Конечно, никто не запрещает добавить описание требования, картинки и таблицы - весь Markdown к вашим услугам.
Так выглядит рендер страницы:
Для упрощения создания типовых страниц можно воспользоваться расширением Templater и использовать шаблоны. Так выглядит шаблон для требования:
|
Тесты
Переходя по ссылке к "Vertical Jump testcase", видим следующий файл:
|
Здесь появилось что-то новенькое. Текст, отделённый тремя дефисами называется YAML frontmatter и представляет собой произвольный набор ключ-значение. Это поможет нам автоматически получать информацию о тесте. Обратите внимание на TODO. Он был отображён на странице Dashboard. Поле sv_name
призвано помочь внешнему скрипту обновлять информацию по результатам регрессий.
Группы покрытия
Взглянем на "Walk speed covergroup"
|
Здесь мы снова видим YAML frontmatter. Поле cg_name
есть название соответствующей группы покрытия в тестбенче. Поле cp_names
служит аналогичной цели.
Ниже находится блок кода. Dataview - это расширение Obsidian для исполнения поисковых запросов и динамического отображения результатов на странице. Именно Dataview рисовал содержимое страниц VPTD и Dashboard. Синтаксис запросов схож с SQL. На этой странице мы ищем среди всех страниц с тегом covergrpoint такие, чьё значение поля cp_name присутствует среди значений поля cp_names данной таблицы. Таким образом, для связи группы с её точками покрытия достаточно перечислить их имена в YAML полях, а Dataview сам отобразит ссылки на страницы. Никакой специфичной для данной страницы информации запрос не содержит, поэтому может быть вынесен в шаблон.
Результат рендера.
Страница точки покрытия выглядит аналогичным образом.
|
Запрос вывернут наизнанку, чтобы отобразить родительскую группу.
Сложные запросы в Dashboard и VPTD
Разберём реализацию запросов в Dashboard.
Поиск непокрытых требований:
|
Первым делом убираем из поиска папку с шаблонами с помощью -"Templates"
. Функция contains
нам уже встречалась, а что есть file.outlinks.file.tags
?
file
это неявная переменная, хранящая все файлы изfrom
;outlinks
- свойство файла, хранящее все исходящие ссылки;- чтобы получить файл по ссылке, используем свойство
file
; - наконец, получаем список тегов файла из свойства
tags
.
Ознакомиться со списком всех внутренних переменных можно в документации Dataview
Чтобы получить список требований с падающими тестами, нужно обратиться к полю Status
на странице теста. Напомню, что это поле содержится в YAML frontmatter, и именно к через это поле мы доберёмся до статуса.
|
Чтобы построить таблицу всех падающих тестов и их ошибок, также нужно фильтровать тесты по полю Status
. Однако в данном случае поле принадлежит страницам, которые запрос получает из from
, поэтому можно обойтись без обращения к file
и frontmatter
.
|
Это наш первый запрос, который строит не список, а таблицу. Вместо list
мы указываем table
и поля, из значений которых будут формироваться столбцы.
Чтобы сделать список всех todo, вместо list/table
пишем task.
|
По умолчанию Dataview скидывает все todo в один список. Чтобы понимать, какая задача принадлежит какой странице, мы просим добавить группировку по ссылке на файл-источник.
Наконец, финал шоу уродцев. Разберём запрос для таблицы VPTD по кусочкам.
|
Когда мы строили таблицу упавших тестов, вы могли заметить, что столбец со ссылкой на тест был создан, хотя бы об этом явно не просили. Таково поведение команды table
. Если этот столбец нужно переименовать, то первым делом мы его полностью убираем с помощью table without id
, после чего добавляем заново под желаемым именем.
|
Мы уже видели, как получить список всех связанных с требованием тестов, однако тогда мы фильтровали требования по признаку "нет теста". Однако для VPTD нам нужно не фильтровать, а отображать тесты в отдельном столбце. Для этого мы прибегнем к помощи встроенной функции filter
, которая, как вы и подумали, принимает список и предикат и возвращает отфильтрованный по этому предикату список.
|
Чтобы сделать таблицу чуточку приятнее взгляду, будем отображать статус тестов не словами, а значками ✅ и ❌. Для этого из результата фильтра нужно взять поле Status
и воспользоваться другой встроенной функцией, map
. Она применяет функцию, переданную во втором аргументе, к каждому элементу списка из первого аргумента.
|
Группы покрытия получаем аналогично тестам, однако будем выводить не только группы, но и отдельные точки.
|
Чтобы получить процент покрытия, просто обращаемся к полю coverage
.
|
Что осталось за бортом
Описанное выше - это ни в коей мере не законченное решение, а всего лишь концепт. Здесь есть как недоработки, так и просто оставленные без внимания вопросы. Коснёмся некоторых из них.
Я не предлагал конкретного способа по связи Obsidian со средством запуска регрессий. Это бессмысленно в отрыве от конкретной инфраструктуры, а решить задачу по обновлению нескольких полей в текстовых файлах совсем не сложно самостоятельно.
У меня нет решения для задачи покрытия составных требований, то есть состоящих из нескольких под-требований. Такое требование будет считаться покрытым, если покрыты все дочерние требования, однако вложенность требований может быть произвольной. Это требует рекурсивных запросов, которые Dataview не поддерживает. Однако Dataview поддерживает исполнение кода JavaScript и, в теории, так решить задачу всё-таки можно. Но пускай это делает кто-то другой.
В начале я говорил, что требование должно быть покрыто тестами, группами покрытия и чекерами, но в дальнейшем про чекеры не вспоминал. Дело в том, что
- Покрытие чекеров принципиально не отличается от любого другого функционального покрытия.
- Не все знакомы с идеей покрытия чекеров. Что это и зачем, я кратко опишу в конце, а для темы рассказа это не так уж важно.
Obsidian может строить графы связности страниц. Отображение можно настраивать различными способами. Возможный результат приведён ниже.
Я не придумал, как можно извлечь пользу из такого графа, поэтому упоминаю его лишь вскользь.
Хотя мы не касались документации на тестбенч и DUT, её вполне можно писать здесь же, в Obsidian. Единственная проблема, которая приходит мне в голову, это создание сложных таблиц. Синтаксис Markdown позволяет описывать простые, но если вам нужно объединять произвольные ячейки, то готовьтесь к боли и разочарованию.
Внимательный читатель мог заметить, что страницы, описывающие группы покрытия, не будут хорошо работать при наличии нескольких экземпляров одной группы. Это решаемо, но как именно, зависит от тестбенча и от желаемого результата, поэтому я не хочу пытаться решить это в общем виде.
Как использовать
Бонус: покрытие чекеров
Раз уж я говорил, что это важно, нужно объяснить почему.
Покрытие чекера - это функциональное покрытие двух событий: чекер сработал и чекер обнаружил ошибку. Первое событие покрывать обязательно, второе -- если есть тесты на инжекцию соответствующей ошибки.
Событие "чекер сработал" значит, что он вообще живой. Согласитесь, довольно неловко написать крутой чекер и забыть его вызвать или подключить. Событие "обнаружил ошибку" показывает, что соответствующий тест с ошибкой имел поведение, похожее на ожидаемое.
Как работать с таким покрытием зависит от того, как вы пишете чекеры, и выходит за рамки статьи.
Заключение
Идея отслеживать ход верификации в Obsidian хоть и родилась в не вполне трезвом рассудке, оказалась вполне рабочей. Представленная концепция позволяет без большого труда следить за статусом различных элементов верификации и находить проблемные места. Конечно, тяжело сказать, насколько это окажется удобным в боевом проекте с двумя, пятью или двадцатью инженерами, но как минимум для домашних проектов можно рассмотреть и такой вариант. В крайнем случае, я надеюсь, что смог познакомить вас с Obsidian, замечательной программой с большими возможностями.