Автогенерация unit-тестов в Claude Code
Claude Code умеет писать тесты сам, но результат зависит от модели и промпта. Как подключить его к zukko.pro и получить тесты, а не заглушки.
4 мин · · Обновлено · Claude Code · тестирование
Подключение
Claude Code — Anthropic-совместимый клиент, поэтому адрес шлюза указывается без /v1: он сам добавляет путь. Два способа задать переменные — через окружение или через settings.json в ~/.claude/.
Через окружение:
export ANTHROPIC_BASE_URL=https://api.zukko.pro
export ANTHROPIC_AUTH_TOKEN=fetch_ваш_ключЧерез settings.json:
{
"env": {
"ANTHROPIC_BASE_URL": "https://api.zukko.pro",
"ANTHROPIC_AUTH_TOKEN": "fetch_ваш_ключ"
}
}Важно писать именно ANTHROPIC_AUTH_TOKEN, а не ANTHROPIC_API_KEY — со вторым Claude Code решает, что вы вошли через официальный аккаунт Anthropic, и просит логин вместо того, чтобы использовать ключ. Ключ создаётся в кабинете на странице https://zukko.pro/app/api-keys и показывается один раз, так что сразу сохраните его в менеджере паролей.
Какую модель ставить по умолчанию
Для генерации тестов имеет смысл разделить задачи по сложности. claude-sonnet-5 быстрый и достаточно точный для рутины: тесты на геттеры, валидацию входных данных, простые обработчики ошибок. claude-opus-5-5 имеет смысл пробовать для кода со сложной веткой логики — там, где нужно продумать граничные случаи, а не просто повторить структуру функции. У него можно включить extended thinking — проверьте на своих сложных модулях, становится ли меньше тестов, которые проходят, но ничего не проверяют. По цене в Zukko обе модели одинаковы ($0.30/$0.30 за 1M токенов входа/выхода).
Обе модели держат контекст в 1 000 000 токенов, так что можно скормить не только тестируемый файл, но и соседние модули, существующие тесты для стиля и конфиг тестового раннера — модель будет писать тесты, которые совпадают по конвенциям с остальным проектом, а не изобретать свой стиль моков.
Переключение модели в Claude Code — через /model claude-opus-5-5 в сессии или флаг при запуске.
Промпт, который не выдаёт бесполезные assert'ы
Модели, если не ограничить их явно, любят генерировать тесты вида expect(result).toBeDefined() — формально тест есть, по факту он ничего не ловит. Работающий промпт обычно включает три ограничения одновременно: явный запрет на тесты без проверки конкретных значений, требование покрыть хотя бы один граничный случай и требование смотреть на существующие тесты в репозитории как на образец.
Пример запроса в сессии Claude Code:
Напиши unit-тесты для src/payments/calculateFee.ts.
Требования:
- каждый тест проверяет конкретное числовое значение или конкретную ошибку, никаких toBeDefined/toBeTruthy без причины
- отдельный тест на нулевую сумму и на отрицательную сумму (должна кидать ValidationError)
- стиль и структура — как в src/payments/__tests__/calculateTax.test.ts
- используй Vitest, как в остальном проекте
Такой промпт с контекстом соседнего тестового файла обычно даёт тесты, которые действительно падают, если сломать логику — можно проверить, испортив одну строку в функции и перезапустив тесты.
Что делать, если генерация обрывается
Если ответ обрывается на середине файла с тестами, это почти всегда не лимит токенов, а таймаут клиента или сети — стоит проверить max_tokens в конфиге и таймаут HTTP-клиента, если вы дергаете модель напрямую через SDK внутри своего скрипта, а не через встроенный агент Claude Code. Сам Claude Code таймауты настраивает разумно по умолчанию, обрывы там обычно случаются на очень длинных файлах — в таком случае имеет смысл просить тесты по одному модулю за раз, благо контекста в 1M токенов хватает, чтобы не терять картину проекта при таком дроблении.
Регрессионный тест по скриншоту бага
Раз модели Claude (как и GPT) принимают изображения, скриншот с багом можно приложить прямо к запросу вместо текстового описания. Модель видит, что именно сломано в интерфейсе, и генерирует тест, который эту ситуацию воспроизводит:
import base64, requests
with open("bug-screenshot.png", "rb") as f:
img = base64.b64encode(f.read()).decode()
resp = requests.post(
"https://api.zukko.pro/v1/messages",
headers={"Authorization": "Bearer fetch_ваш_ключ", "anthropic-version": "2023-06-01"},
json={
"model": "claude-opus-5-5",
"max_tokens": 2048,
"messages": [{
"role": "user",
"content": [
{"type": "image", "source": {"type": "base64", "media_type": "image/png", "data": img}},
{"type": "text", "text": "На скриншоте баг в форме оплаты. Напиши regression-тест на Playwright, который его ловит."},
],
}],
},
)Работает лучше, чем пересказ бага словами: модель видит точное состояние формы, а не интерпретацию человека.
Если модель, на которую завязан CI, выключили
Каталог моделей время от времени обновляется, и модель, зашитая в конфиг CI, может оказаться выключенной — например, так уже произошло с claude-opus-4.6. Запрос к ней возвращает 503 с кодом model_disabled (не 404 и не model_retired):
{"error": {"code": "model_disabled"}}Замену смотрите в актуальном списке GET https://api.zukko.pro/v1/models — для Opus это claude-opus-5-5. Стоит обрабатывать этот код отдельно от прочих ошибок и логировать его — тогда обновление конфига CI занимает одну строчку, а не расследование, почему вдруг все прогоны генерации тестов начали падать.
Контроль расходов
Каждый обычный (не потоковый) ответ шлюза несёт заголовок X-Zukko-Cost-Micros — стоимость именно этого запроса в микродолларах (1 000 000 = $1) — и X-Fetch-Balance-Cents с остатком после списания (несмотря на название, тоже в микродолларах). У потоковых ответов — а сам Claude Code работает именно так — этих заголовков нет: расход сессий Claude Code смотрите в кабинете, через GET /v1/usage или GET /v1/balance. Если вы автоматизировали прогон генерации тестов по всем модулям проекта скриптом без стриминга, эти заголовки удобно логировать, чтобы понимать, на каких файлах модель "думает" дольше и дороже — обычно это сигнал, что там сложная логика и тесты стоит перепроверить руками.
Полную историю списаний (общую на весь аккаунт, все ключи вместе) можно посмотреть через GET /v1/usage с курсорной пагинацией, а текущий баланс — через GET /v1/balance. Оба требуют ключ:
curl https://api.zukko.pro/v1/balance \
-H "Authorization: Bearer fetch_ваш_ключ"Если баланс закончится, шлюз вернёт 402 ещё до обращения к модели — запрос ничего не будет стоить, но и тестов вы не получите, так что для CI-пайплайна, который гоняет генерацию тестов на каждый PR, стоит настроить дневной лимит на ключе на странице ключа в кабинете, чтобы один сорвавшийся цикл не съел весь бюджет разом.
zukko
Платите в 25×
меньше
за Claude Code & ChatGPT
Один ключ fetch_* и base URL api.zukko.pro — в Cursor, Claude Code, Codex и любом SDK.
Похожие статьи
- Агенты opencode: как настроить роли, модели и инструментыСвой агент в opencode — это роль, модель и список разрешений. Показываем конфиг и пример, где рутину делает дешёвая модель, а код правит сильная.
- Ключи OpenAI API в открытом доступе: почему ими нельзя пользоватьсяОткуда берутся «бесплатные» ключи на GitHub, почему пользоваться ими опасно и для вас, и для владельца, и как защитить собственный ключ от такой же утечки.
- Ошибки GLM API: почему не работает запрос и как это исправитьНеверный id модели, переполненный контекст 128K, ключ, баланс, лимиты: типичные причины ошибок GLM API и быстрый способ найти свою.
- Plan mode в Claude Code: сначала план, потом правки в кодеВ plan mode Claude Code читает код и предлагает план, но ничего не правит, пока вы не согласитесь. Как включить, использовать и во сколько это обходится.