Sharding из главы про параллельность создаёт неочевидную проблему с отчётностью. Когда набор разбит на несколько машин и каждая проходит свою часть, у каждой получается собственный отчёт про свою треть тестов. В итоге вместо одной цельной картины прогона - три обрывка, по которым нельзя увидеть общий результат: сколько всего прошло, что упало, где trace. Отдельные отчёты шардов бесполезны как общий отчёт - их нужно сшить в один.
Решение - промежуточный формат blob. На CI reporter переключают на blob: вместо готового HTML каждый шард пишет машиночитаемый blob-отчёт - самодостаточный кусок данных о своей части прогона, включая trace'ы и вложения. Blob не предназначен для чтения человеком напрямую; это сырьё, из которого позже собирают единый человекочитаемый отчёт. Каждый шард производит свой blob и складывает его как артефакт CI.
Дальше blob-отчёты всех шардов собирают в одном месте. После того как параллельные job'ы шардов завершились, отдельная job скачивает все их blob-артефакты - и получает полный набор кусков прогона. Это точка сборки: здесь впервые появляется вся информация о прогоне целиком, разложенная по blob-файлам, готовая к слиянию в один отчёт. Сборочную job ставят зависимой от шардов, чтобы она стартовала после них.
Сшивает всё команда merge-reports. npx playwright merge-reports с указанием reporter html и каталогом, куда сложены все blob'ы, собирает из них единый HTML-отчёт всего прогона - как если бы набор шёл на одной машине. В отчёте видны все тесты, все падения и все trace'ы вместе, а не по кускам. Из blob можно собрать и другие форматы, но html - тот, что дают команде для разбора.
Полезно один раз увидеть обе части - настройку blob на шардах и команду слияния. Ниже - переключение reporter на blob для CI и вызов merge-reports над каталогом собранных blob'ов. К этой паре возвращаются, настраивая sharded-пайплайн: сначала каждый шард пишет blob, затем отдельная job сливает их в один отчёт, и только он идёт команде.
Структура пайплайна из этого следует прямо. Матрица шардов - несколько параллельных job'ов, каждая с blob-репортером и загрузкой своего blob-артефакта. Затем финальная job с needs на всю матрицу, которая скачивает все blob-артефакты и вызывает merge-reports. Так параллельность из главы про масштабирование получает целостную отчётность: тесты идут врозь для скорости, а результат собирается воедино для разбора.
Без этой сборки sharded-прогон теряет главное - единую картину. Три отдельных отчёта заставляют вручную сопоставлять, что и где упало, а общего числа пройденных не дают вовсе; trace конкретного падения приходится искать по шардам. Merge-reports возвращает то, ради чего отчёт и нужен: один взгляд на весь прогон. Поэтому в любом sharded-пайплайне слияние - не опция, а обязательный финальный шаг.
Типичные провалы здесь предсказуемы. Оставить на шардах обычный html-репортер вместо blob - и получить несшиваемые куски, из которых единый отчёт уже не собрать. Забыть загрузить или скачать blob-артефакты - и сборочной job'е будет нечего сливать. И не поставить merge-job зависимой от шардов - она стартует раньше, чем blob'ы готовы. Пишите blob на каждом шарде, собирайте артефакты в зависимой job и сливайте их merge-reports в единый отчёт.
// На CI при sharding каждый шард пишет blob вместо html
export default defineConfig({
reporter: process.env.CI ? 'blob' : [['html'], ['list']],
})# Отдельная job: скачать все blob-артефакты шардов и сшить в один отчёт
npx playwright merge-reports --reporter html ./all-blob-reports
# из собранных blob'ов получается единый HTML-отчёт всего прогона