Отчёт о регрессиях
Сценарий регрессии полезен, когда его результат можно объяснить человеку, который не писал тест. Одной красной строки недостаточно: нужно понимать действие читателя, ожидаемое условие, фактическое наблюдение и среду. Даже при успешном результате важно знать, какие свойства проверялись и какие задачи остались за пределами набора.
В последнем уроке подготовим конфигурацию отчётов и небольшой набор из трёх самостоятельных сценариев. Полный проект находится в 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-матрицей, а действия человека выбираются отдельно.
Пока результат этой главы — подготовленные сценарии, конфигурация и незаполненная карточка наблюдений. Для утверждений о прохождении, причинах отказа и пригодности будущего отчёта нужно отдельно выполнить проект и оценить полученные данные. Сохранение этой границы делает материалы полезными для обучения: читатель видит ожидаемую договорённость и понимает, как затем подтвердить её фактически.