Перейти к содержанию

Отчёт о регрессиях

Сценарий регрессии полезен, когда его результат можно объяснить человеку, который не писал тест. Одной красной строки недостаточно: нужно понимать действие читателя, ожидаемое условие, фактическое наблюдение и среду. Даже при успешном результате важно знать, какие свойства проверялись и какие задачи остались за пределами набора.

В последнем уроке подготовим конфигурацию отчётов и небольшой набор из трёх самостоятельных сценариев. Полный проект находится в lesson-24/expected архива продолжения. Тесты сейчас не выполнялись. Реальных HTML/JSON-отчётов, trace, screenshots и статусов успеха в архиве нет; regression-template.md является пустой схемой будущей записи.

Отчёт начинается с понятной договорённости

Первый сценарий защищает учебный прежний .php адрес: 200 без скрытого редиректа, конечный URL, H1 и характерный текст статьи. Второй наблюдает скачанный каталог: имя файла и точное содержимое из четырёх курсов. Третий проверяет доступную ошибку формы: фокус, invalid и текст сообщения после неправильной почты.

Эти сценарии не перечисляют всё приложение. Мы выбрали три разных читательских результата, чтобы показать, как отчёт связывается с задачей. Предпросмотр файла, метаданные, мобильное меню и эталон изображения описаны отдельными состояниями прежних уроков. Последний файл не включает их автоматически и не заявляет полный регрессионный охват.

Каждый тест получает независимый браузерный контекст. Download использует отдельный outputPath, массив курсов остаётся неизменяемым, а сообщение не сохраняется сервером. Поэтому отчёт не зависит от обязательного порядка трёх тестов. Если позднее добавить общий серверный ресурс, изоляцию понадобится определить заново, а не рассчитывать только на название сценария.

Шаги должны объяснять место отказа

В первом сценарии HTTP и браузерное содержание разделены через test.step(). Так будущий результат может показать, нарушился ли статус пути или открылась неправильная статья.

await test.step('Сверить HTTP без скрытого redirect', async () => {
  const response = await request.get(path, { maxRedirects: 0 });
  expect(response.status()).toBe(200);
});
await test.step('Сверить статью в браузере', async () => {
  await page.goto(path);
  await expect(page).toHaveURL(`http://127.0.0.1:4407${path}`);
  await expect(page.getByRole('heading', {
    name: 'Основы HTML', level: 1, exact: true
  })).toBeVisible();
  await expect(page.locator('article')).toContainText('Учебный материал c001');
});

Имена шагов описывают наблюдения. Они не содержат заранее утверждённого «всё успешно» и не заменяют assert. Если путь выдаёт 404, второй шаг не станет объяснением правильной статьи. Если статус верен, но сервер возвращает оглавление, содержательный assert укажет другой уровень нарушения.

В рабочем отчёте полезно сохранить связь со значимостью страницы. Отказ важного входного материала влияет иначе, чем косметическое отличие редкого вспомогательного блока. Серьёзность выводится из задачи читателя и масштаба изменения, а не только из количества упавших утверждений.

Три представления одного будущего запуска

Конфигурация сохраняет консольный list и добавляет два reporter: HTML для просмотра человеком и JSON для последующей обработки. Они получат данные только тогда, когда выбранный проект будет отдельно выполнен.

reporter: [
  ['list'],
  ['html', { outputFolder: 'reports/html', open: 'never' }],
  ['json', { outputFile: 'reports/results.json' }]
],

HTML не открывается автоматически благодаря open:'never'. JSON не является нашим вручную написанным перечнем желаемых успехов: runner создаст его по фактическим событиям. Поэтому папка reports сейчас отсутствует. Придумывать файл с passed означало бы подменить выполнение текстом, хотя мы пока только готовим исходники.

Форматы и параметры представлены в документации reporters Playwright. Для этой лаборатории пути относятся к отдельной учебной папке. Они не пишут отчёты в production ProfessorWeb и не запускают публикацию. Перенос файла конфигурации в рабочий проект требует согласовать размещение и срок хранения артефактов.

Полезное вложение к сценарию

Через test.afterEach() прикрепим небольшую JSON-договорённость: имя лаборатории, закреплённые версии, четыре курса, пятьдесят уроков и номер попытки. Это исходные условия, а не измеренный результат работы приложения. Значение retry придёт от будущего runner; сейчас оно не записано в отчёт.

await testInfo.attach('scenario-contract', {
  body: JSON.stringify({
    laboratory: 'catalog-test-lab-advanced',
    node: '24.21.0', playwright: '1.64.0',
    courses: 4, lessons: 50, retry: testInfo.retry
  }, null, 2),
  contentType: 'application/json'
});

Скачанный JSON также прикрепляется после проверки содержимого. Он содержит только вымышленные публичные данные каталога. API TestInfo позволяет прикладывать файл или данные из памяти. В настоящем проекте выбирать артефакт нужно осторожнее: cookie, токены, введённые контакты и полный приватный ответ обычно не нужны для объяснения регрессии.

Контрактное вложение не подтверждает установленную среду само по себе. Оно записывает заявленные условия исходников. Перед исполнением нужно отдельно обеспечить версии, а для расследования зафиксировать фактическую среду runner. Эта разница особенно важна после обновления зависимости: старый текстовый номер не заставит другой установленный браузер стать прежним.

Карточка наблюдения и гипотеза причины

Пустой шаблон предлагает записать ревизию приложения, сценарий, среду, шаг, ожидание, фактическое наблюдение, статус и воспроизводимость. Отдельные поля оставлены для влияния на читателя, причины или пока гипотезы, принятого решения и проверки после исправления. Сейчас все поля фактического выполнения пусты.

Пример различия формулировок: «запрос сохранённого пути вернул 404» относится к наблюдению, если это подтверждено ответом. «ошибка правила сервера» пока является гипотезой, пока правило не исследовано. Смешение этих предложений может направить исправление в неправильное место, особенно когда браузер и API наблюдают разные части цепочки.

Для нестабильного сценария дополнительно важны первая попытка и повтор. У нас retries равен нулю, а trace сохраняется только при будущей неудаче. Точное место файла сообщит runner. Успешный сценарий не обязан оставить trace, а отсутствие файла сейчас соответствует отсутствию выполнения, а не безошибочности сайта.

Завершение учебной серии

Теперь серия содержит двадцать четыре локальных урока: от наблюдаемого сценария и локатора до файлов, адресов, метаданных, доступности и отчёта. Исходники сохраняют один предметный мир с четырьмя курсами и пятьюдесятью уроками. Это позволяет связывать новые механизмы с уже понятными данными, не выдавая каждую главу за новый независимый продукт.

Дальнейший рабочий набор потребуется составить по настоящим задачам ProfessorWeb. Он может включать защищённые адреса, поиск, общие шаблоны, sitemap и важные учебные последовательности. Количество страниц само по себе не определяет, какие браузерные сценарии нужны: многие свойства проверяются чтением сборки и HTTP-матрицей, а действия человека выбираются отдельно.

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