Создание скриншотов при ошибках

В процессе автоматизированного тестирования веб-приложений крайне важно иметь возможность фиксировать состояние страницы в момент возникновения ошибки. Protractor, как инструмент для тестирования Angular-приложений на JavaScript, предоставляет гибкие возможности для создания скриншотов, которые помогают анализировать причины сбоев и ускоряют отладку.

Подключение необходимых модулей

Для создания скриншотов потребуется модуль fs для работы с файловой системой и встроенные возможности WebDriver. В Protractor WebDriver доступен через объект browser. Основные зависимости подключаются следующим образом:

const fs = require('fs');

Создание скриншотов напрямую через browser осуществляется методом takeScreenshot(), который возвращает промис с изображением в формате base64:

browser.takeScreenshot().then(function(png) {
    const stream = fs.createWriteStream('screenshot.png');
    stream.write(Buffer.from(png, 'base64'));
    stream.end();
});

Автоматическое создание скриншотов при падении теста

Protractor позволяет интегрировать создание скриншотов с системами тестирования, такими как Jasmine. Для этого используется глобальный хук afterEach:

afterEach(async function() {
    const spec = jasmine['currentTest'] || jasmine['currentSpec'];
    if (spec.status === 'failed') {
        const png = await browser.takeScreenshot();
        const path = `screenshots/${spec.description.replace(/\s+/g, '_')}.png`;
        fs.writeFileSync(path, png, {encoding: 'base64'});
    }
});

Важные моменты:

  • Путь сохранения: Рекомендуется создавать отдельную директорию screenshots для хранения всех снимков.
  • Имя файла: Используется описание теста для генерации имени, при этом пробелы и специальные символы заменяются на подчеркивания.
  • Асинхронность: Методы takeScreenshot и writeFileSync корректно работают с промисами и потоками, что предотвращает потерю данных при параллельном выполнении тестов.

Организация структуры хранения скриншотов

Для удобства анализа ошибок можно использовать структуру директорий по дате или по наборам тестов:

screenshots/
├─ 2026-01-07/
│  ├─ login_test_failed.png
│  └─ cart_test_failed.png
├─ 2026-01-06/
│  └─ checkout_test_failed.png

Генерация директорий выполняется с помощью fs.existsSync и fs.mkdirSync:

const dir = `screenshots/${new Date().toISOString().slice(0,10)}`;
if (!fs.existsSync(dir)) {
    fs.mkdirSync(dir, { recursive: true });
}
const path = `${dir}/test_failed.png`;
fs.writeFileSync(path, png, {encoding: 'base64'});

Скриншоты отдельных элементов

Иногда требуется фиксировать не всю страницу, а конкретный элемент. Для этого используется метод takeScreenshot на элементе:

const elem = element(by.id('loginButton'));
const png = await elem.takeScreenshot();
fs.writeFileSync('element_screenshot.png', png, {encoding: 'base64'});

Это особенно полезно для динамически изменяющихся компонентов и позволяет экономить место, фокусируясь только на проблемных областях.

Взаимодействие с отчетами

Созданные скриншоты можно интегрировать в HTML-отчеты Jasmine или Allure. Простейший способ — сохранять файлы в папку отчета и использовать их ссылками:

afterEach(async function() {
    if (jasmine['currentTest'].status === 'failed') {
        const png = await browser.takeScreenshot();
        const path = `reports/screenshots/${jasmine['currentTest'].description.replace(/\s+/g, '_')}.png`;
        fs.writeFileSync(path, png, {encoding: 'base64'});
        console.log('Скриншот сохранён: ' + path);
    }
});

Практические советы

  • Всегда использовать уникальные имена файлов, чтобы не перезаписывать предыдущие скриншоты.
  • Использовать асинхронные функции (async/await) для корректного выполнения при большом количестве тестов.
  • Комбинировать скриншоты с логированием состояния приложения для более точного анализа.
  • Ограничивать размеры скриншотов или использовать сжатие при работе с большим количеством тестов, чтобы не перегружать диск.

Создание скриншотов при ошибках существенно повышает качество тестирования и ускоряет диагностику проблем в Angular-приложениях с использованием Protractor.