chimera-test-the-wiring-not-the-class
Класс, собранный вручную в тесте, доказывает, что класс работает, а не что до него что-то доходит, — покрывайте тот путь, которым система идёт в production.
Присвоено человеком, который прочитал карточку, а не заявлено файлом о самом себе. Карточка, которую агент выводит во время запуска, поглотившего недоверенное содержимое, рождается заражённой и удерживается на разбор, прежде чем её вообще извлекут.
Когда это вспоминается
- в тестах работает, в приложении нет
- добавил компонент за фабрикой или реестром
- флаг по умолчанию выключен
- тесты зелёные, поведение сломано
Ценность обычно лежит в разделах «Избегать» и «Проверить». «Делать» — это раздел, который пишут все.
Текст карточки выше — перевод. Английский оригинал — это то, что импортирует командная строка, что читает агент во время работы и что подтверждает хеш ниже.
Повод
Вы построили компонент, до которого production добирается опосредованно: через фабрику, реестр, загрузчик плагинов, флаг конфигурации, роутер, точку входа CLI, контейнер внедрения зависимостей. Ваши тесты конструируют его напрямую и вызывают его методы.
Каждый такой тест может проходить, пока компонент в работающей системе недостижим, — потому что ни один из них не задействует регистрацию, значение флага по умолчанию или ветку в сборщике, решающую, включать ли компонент вообще.
Это не относится к чистой функции, которую вызывающие импортируют и вызывают напрямую. Там импорт и есть связывание, и unit-тест его покрывает. Не относится это и к случаю, когда вы намеренно тестируете алгоритм в изоляции: такие тесты верны и должны остаться; карточка утверждает лишь, что сами по себе они недостаточны.
Делать
-
Назовите точку входа, до которой пользователь действительно доходит: подкоманду CLI, HTTP-маршрут, цикл запуска агента, запланированную джобу. Запишите её до того, как писать тест.
-
Напишите хотя бы один тест, который стартует оттуда и не передаёт вашему компоненту никаких аргументов конструктора. Если тесту приходится называть ваш класс, чтобы функция сработала, он тестирует не связывание.
-
Стройте объект так, как его строит production, — вызывайте настоящую фабрику или загрузчик конфигурации:
# WRONG — proves the class, not the wiring: the component is handed to the thing under test, # so the test passes whether or not anything in production ever hands it over. assert "reminder" in render(feature=Feature(text="reminder")) # RIGHT — build it the way the entry point builds it, then look for the same observable assert "reminder" in build_the_real_way(config).render()Собственный случай Chimera стоит назвать, потому что класс никогда не был сломан. У skill cards были работающий retriever, работающее хранилище и работающий инжектор — а
chimera/config.py:244содержитskill_cards: bool = Field(default=False, ...), поэтому на стандартной установке ничего никогда не подставлялось. Все unit-тесты проходили. Измерение, которое в итоге это поймало, посчитало отчеканенные навыки против подставленных и получило 39 против нуля. -
Проверяйте наблюдаемое, которое может появиться, только если до компонента дошли: текст в собранном промпте, записанную строку, строку лога, код выхода.
-
Проверяйте значение по умолчанию. Если функциональность выходит за флагом, добавьте отдельный тест, который читает значение по умолчанию без переопределений и проверяет, каково оно. Набор, который всегда гоняется с принудительно включённым флагом, не может сказать вам, что получают пользователи.
Избегать
Собирать руками коллабораторов, которых связывает production. Форма сбоя — класс-обработчик с полным unit-покрытием, который роутер не регистрирует, или возможность, чей ключ конфигурации по умолчанию выключен: класс верен, тесты верны, а в продукте функция ничего не делает. Ничего не красное, поэтому ничего и не расследуют, и разрыв доживает до момента, когда человек попробует функцию руками.
Также не подделывайте тот шов, который вы и собирались покрыть. Патч фабрики или заглушка загрузчика конфигурации, возвращающая объект с вашим компонентом, удаляет ровно тот код, ради которого тест существовал:
monkeypatch.setattr(mod, "load_plugins", lambda: [MyPlugin()])
Подделывайте на самой внешней границе — сетевой клиент, часы, вызов LLM, — и пусть всё между точкой входа и вашим компонентом будет настоящим.
Проверить
Удалите связывание и запустите набор. Закомментируйте строку регистрации: декоратор
@register, запись в словаре диспетчеризации, вызов include_router(...), значение по умолчанию в
схеме конфигурации.
Затем двоичный вопрос: покраснел ли тест, и был ли это тест, который ни разу не называет ваш класс по имени?
Если набор остался зелёным — покрытие у вас только на уровне класса, а связывание не тестируется.
Если единственный красный тест — тот, что конструирует класс напрямую, ответ тот же. После этого
верните строку и убедитесь, что снова зелено, — и запустите git diff перед коммитом, чтобы
удалённая регистрация не уехала в релиз.
Риск
Тесты через точку входа медленнее, тяжелее в отладке и хуже локализуют: когда такой падает, вы знаете, что функция сломана, но не знаете, который из десяти компонентов её сломал. Это реальная цена, и неверная реакция на эту карточку — удалить свои unit-тесты в пользу end-to-end. Держите и те и другие: тест связывания сообщает, что сломалось, unit-тест — что именно.
Проход через настоящую точку входа может к тому же задеть то, что в CI задевать не хочется: платный API, живую базу, файловую систему за пределами песочницы. Если единственный способ дойти до точки входа — потратить деньги или изменить production, не форсируйте; покройте вместо этого функцию-сборщик напрямую и примите, что вы на шаг не дошли до настоящего пути.
И эта карточка ловит достижимость, а не корректность. Функция может быть безупречно связана с точкой входа и всё равно выдавать неверный ответ, так что зелёный тест связывания — не лицензия пропускать проверку того, что вывод на самом деле говорит.
Как применить
Карточка — это данные. Склонируйте репозиторий и импортируйте её по пути: всё, что приходит по сети, считается заражённым и удерживается до одобрения — это и есть желаемое поведение, и поэтому здесь нет установщика в одну строку.
git clone https://github.com/brcampidelli/chimera-agent.gitchimera skills-import chimera-agent/skills/chimera-test-the-wiring-not-the-class/SKILL.mdЦелостность
SHA-256 файла в опубликованном виде. Импортёр может проверить, что полученное совпадает с показанным на этой странице.
564f2b0aaff3bbb51ca9bfa013d89e3d47d92166f498803c688c3b859b378475