T27.AI

Блог

Четыреста двенадцать тестов, которые были предложениями

2026-08-22 · 7 мин чтения

Тридцать четыре файла conformance-векторов, 512 кейсов, ни один никогда не исполнялся — а когда посчитали, 412 из них не несли ни входов, ни ожидаемых значений. Как корпус становится декоративным, почему первый классификатор дал 147 там, где независимый проход дал 100, и трёхвердиктный реестр (исполняется / именованный долг / аспирационное), позволяющий заменить большое ложное число маленьким истинным.

TestingCIFPGAMeasurementSelf-critique

В репозитории было тридцать четыре файла conformance-векторов. Пятьсот двенадцать тест-кейсов. Ни один не исполнялся против железа, которое описывал, — а когда мы наконец посчитали, что внутри, четыреста двенадцать из этих кейсов не несли данных вообще: идентификатор, предложение и больше ничего. Ни входов. Ни ожидаемых значений. Документация в форме теста.

Как корпус становится декоративным

Ничего драматичного не произошло. Файл лёг в каталог conformance. CI-задача прочитала его сохранённое поле «verdict» — строку, которую кто-то однажды напечатал, — и вывела в сводку прогона. Лёг ещё файл. Счёт вырос. «Тридцать четыре файла векторов» стало фразой, которую говорят о проекте, и в ней было верно всё, кроме главного: ни один раннер их не открывал.

Разрыв легко не заметить, потому что обе половины выглядят как работа. Написать файл векторов — это работа. Прочитать сводку со словом CLEAN — успокаивает. Пропущенный шаг — собственно применить векторы к RTL — не оставляет следов, когда его нет: у отсутствия нет вывода.

Счёт и счётчик, который о нём соврал

Первый написанный нами классификатор сообщил про 147 кейсов с данными. Независимый проход на другом языке — про 100. Расхождение двух приборов — не погрешность, которую усредняют: один из них неверен, и пока неизвестно который, ни одно число нельзя записывать.

Неверным был наш. Он резал каждый JSON-объект по запятым в поисках полей — а описания содержат запятые. «Sync FIFO reports is_sync=true, is_async=false» распадается на два фрагмента, второй из которых выглядит ровно как нераспознанное поле. Каждый описательный кейс с запятой в предложении повышался до «несущего данные». Переписанный сканер отслеживает состояние строки и собирает только настоящие ключи; теперь он воспроизводит независимый счёт на всех тридцати четырёх файлах.

$ tri vectors debt        # 2026-08-22, as first measured
1 executed, 9 debt, 24 prose-only (34 files);
512 cases, 100 carrying data (19%).

$ tri vectors debt        # after spi joined the executed set
2 executed, 8 debt, 24 prose-only (34 files);

Три вердикта, никогда два

Первый порыв при такой находке — «запустить их все». Этот порыв и породил проблему: он считает каждый артефакт тестом, который просто пока не запускали. Большинство из них запустить нельзя вовсе — не из-за бага, а потому что они описывают поведение, которого не выставляет ни один интерфейс дизайна. Векторы одного модуля проверяют паттерны на светодиодах; в спецификации нет ни одной светодиодной функции.

Поэтому реестр сортирует каждый файл ровно в один из трёх вердиктов, и третий — самый важный:

Два вердикта заставляют каждый неисполнимый артефакт маскироваться под один из них — и все они оседают в «пока нет». Третья категория и позволяет назвать настоящее число: честный потолок исполнения здесь — десять файлов, не тридцать четыре.

Храповик

Починить двадцать четыре файла — решение, которым владеет кто-то другой. Остановить двадцать пятый — нет. Гейт замораживает существующие описательные файлы именованным долгом и падает, когда приходит новый, — тем же паттерном baseline-as-debt, который репозиторий уже использует в других местах. Подсаженный описательный файл ловится с числом кейсов; подсаженный файл с единственным полем ввода проходит. Класс не может вырасти снова без того, чтобы кто-то осознанно записал, что он этого хочет.

Два модуля теперь исполняются по-настоящему: восемнадцать кейсов в семи группах у одного, три у другого, у каждого — контроль подсаженной поломкой, доказывающий, что проверка реагирует. Это небольшое число, и оно истинное — единственное свойство, ради которого его стоит иметь. (Сначала здесь стояло «девятнадцать». Раннер печатает восемнадцать; поправка записана открыто, а не внесена молча: посту о честном счёте не пристало округлять собственный.)

К чему это обобщается

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

Чего это не решает

Пруфы

Каждая цифра выше измерена, и рядом с ней названы её пределы.