feat(web-test): бюджеты дедлайнов в конфиг + пробой сброса прерывает контекст

Числа были зашиты в код и подобраны на лёгком синтетическом стенде. На тяжёлом
прикладном решении тот же resetState честно идёт дольше — и упирался бы в чужой
дефолт без возможности его поднять.

- `deadlines: {...}` в webtest.config.mjs переопределяет любой бюджет поштучно.
  Неизвестный ключ или неположительное значение — ошибка до старта прогона:
  опечатка в имени означала бы, что переопределение молча не действует.
- Пробой resetState теперь ПРЕРЫВАЕТ контекст, а не пишет строку и едет дальше.
  После неудавшегося сброса состояние UI неизвестно, и переиспользование слота
  утекало бы грязным состоянием в следующий тест — худший исход плохо подобранного
  бюджета: тихий дрейф вместо видимой ошибки. Теперь слишком тесный бюджет стоит
  перезапуска контекста, но никогда — неверного результата теста.

Проверено: опечатка ключа → внятная ошибка с перечнем допустимых; deadlines
{resetState:1} → пробой виден строкой, контекст прерван, следующий тест зелёный.
check.mjs 6/6.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
Nick Shirokov
2026-07-15 18:03:10 +03:00
parent 9352d28008
commit 57c101ef3c
3 changed files with 72 additions and 6 deletions
+34
View File
@@ -473,6 +473,13 @@ export default {
screenshot: 'on-failure', // 'every-step' | 'off'
record: false,
// Бюджеты служебных операций (мс). Дефолты рассчитаны на лёгкий стенд; тяжёлому
// прикладному решению честно нужно больше — переопределяются поштучно.
deadlines: {
resetState: 60000, // встроенный сброс на тяжёлых формах
closeContext: 30000,
},
// Дефолтный тег-фильтр. Применяется только если CLI не передал --tags.
// Удобно для сценариев «прогон по умолчанию = smoke», при этом --tags=full
// (или --tags=) с CLI прозрачно перекрывает.
@@ -1031,6 +1038,33 @@ Timeout (30000ms) — verdict: hang (renderer unresponsive, browser alive)
- Весь путь очистки (скриншот, `teardown`, `afterEach`, сброс, запись/остановка видео, закрытие контекстов,
`disconnect`) ограничен дедлайнами. Пробой дедлайна печатается строкой `! <операция>: timed out after Nms`
и прогон едет дальше — молча зависнуть путь очистки больше не может.
#### Бюджеты служебных операций (`deadlines`)
Дефолты рассчитаны на лёгкий стенд и переопределяются поштучно ключом `deadlines` в `webtest.config.mjs`
(см. §7). Неизвестный ключ или неположительное значение — ошибка до старта прогона (опечатка в имени ключа
означала бы, что переопределение молча не действует).
| Ключ | Default | Что ограничивает |
|------|---------|------------------|
| `screenshot` | 10000 | Скриншот при падении |
| `teardown` / `afterEach` | 15000 | `teardown` теста / хук `afterEach` |
| `setActive` | 5000 | Переключение активного контекста |
| `resetState` | 20000 | Встроенный сброс состояния (до 10 итераций `getFormState` + `closeForm`) |
| `startRecording` / `stopRecording` | 15000 / 40000 | Видео (у ffmpeg внутри свои 30 с) |
| `closeContext` | 20000 | Закрытие/прерывание контекста |
| `disconnect` | 30000 | Финальное закрытие браузера |
| `hooks` | 120000 | `afterAll` / `cleanup` |
| `abortAll` | 30000 | Весь блок прерывания одного зависшего теста |
| `probe` | 2000 | Пробники рендерера/браузера при таймауте |
`prepare` и `beforeAll` **не ограничены сознательно**: `prepare` пересобирает стенд, и его честная
длительность зависит от размера прикладного решения; его падение обязано оставаться фатальным.
**Пробой `resetState` прерывает контекст** (а не просто пишет строку): состояние UI после неудавшегося
сброса неизвестно, и переиспользование слота утекло бы грязным состоянием в следующий тест — худший исход
для плохо подобранного бюджета. Вместо этого слот уничтожается, следующий тест получает чистый через
`ensureContext`. Слишком тесный бюджет стоит перезапуска контекста, но никогда — неверного результата теста.
- Тело прерванного теста продолжает жить (промис не отменяем). Его поздние вызовы к движку блокируются
с ошибкой `test abandoned (timeout)` — иначе `finally` упавшего теста кликал бы в окне следующего.