Логирование с Winston

Логирование является неотъемлемой частью автоматизированного тестирования. Оно позволяет отслеживать выполнение тестов, фиксировать ошибки и предупреждения, а также анализировать поведение скриптов в различных условиях. В среде Node.js одним из самых популярных инструментов для структурированного логирования является библиотека Winston. В сочетании с Puppeteer она обеспечивает прозрачность и управляемость процессов браузерного автоматизированного тестирования.


Установка и базовая конфигурация

Для начала необходимо установить Winston и его зависимости:

npm install winston

После установки создается базовый конфиг логгера:

const { createLogger, format, transports } = require(&

const logger = createLogger({
  level: 'info',
  format: format.combine(
    format.timestamp({ format: 'YYYY-MM-DD HH:mm:ss' }),
    format.printf(info => `${info.timestamp} [${info.level.toUpperCase()}]: ${info.message}`)
  ),
  transports: [
    new transports.Console(),
    new transports.File({ filename: 'logs/test.log' })
  ],
});

Ключевые моменты конфигурации:

  • level: определяет минимальный уровень логируемых сообщений (error, warn, info, debug).
  • format.timestamp: добавляет временную метку к каждому сообщению.
  • format.printf: позволяет гибко настраивать вывод в логах.
  • transports: указывает каналы логирования — консоль и файл.

Интеграция Winston с Puppeteer

При работе с Puppeteer логирование позволяет фиксировать шаги теста, состояние страницы и ошибки выполнения. Пример использования логгера в асинхронной функции теста:

const puppeteer = require('puppeteer');

(async () => {
  logger.info('Запуск браузера');
  const browser = await puppeteer.launch({ headless: true });
  const page = await browser.newPage();

  try {
    logger.info('Открытие страницы https://example.com');
    await page.goto('https://example.com', { waitUntil: 'networkidle2' });

    const title = await page.title();
    logger.info(`Заголовок страницы: ${title}`);

    const element = await page.$('h1');
    if (element) {
      logger.info('Элемент h1 найден');
    } else {
      logger.warn('Элемент h1 не найден');
    }

  } catch (error) {
    logger.error(`Ошибка при выполнении теста: ${error.message}`);
  } finally {
    await browser.close();
    logger.info('Браузер закрыт');
  }
})();

Особенности подхода:

  • Каждое ключевое действие сопровождается logger.info.
  • Потенциальные проблемы фиксируются с помощью logger.warn.
  • Исключения обрабатываются через logger.error, что упрощает диагностику.

Настройка разных уровней логирования

Winston поддерживает иерархию уровней логов:

Уровень Назначение
error Критические ошибки, приводящие к срыву теста
warn Потенциальные проблемы, не прерывающие выполнение
info Основные шаги теста и полезная информация
debug Детальная информация для отладки
verbose Расширенные сообщения, полезные при анализе сложных сценариев

Пример добавления уровня debug и фильтрации сообщений:

const logger = createLogger({
  level: 'debug',
  format: format.combine(
    format.colorize(),
    format.timestamp({ format: 'YYYY-MM-DD HH:mm:ss' }),
    format.printf(info => `${info.timestamp} [${info.level}]: ${info.message}`)
  ),
  transports: [
    new transports.Console({ level: 'debug' }),
    new transports.File({ filename: 'logs/debug.log', level: 'debug' })
  ],
});

Логирование действий страницы и ошибок Puppeteer

Для детального анализа полезно логировать события браузера:

page.on('console', msg => {
  logger.info(`Console: ${msg.text()}`);
});

page.on('pageerror', error => {
  logger.error(`Page error: ${error.message}`);
});

page.on('requestfailed', request => {
  logger.warn(`Request failed: ${request.url()} - ${request.failure().errorText}`);
});

Это позволяет фиксировать:

  • Сообщения из console.log страницы.
  • Ошибки выполнения скриптов на сайте.
  • Неудачные сетевые запросы.

Создание собственного транспорта для Puppeteer

Иногда нужно логировать отдельно данные Puppeteer, чтобы не смешивать с общими логами. Winston позволяет создавать кастомные транспорты:

const { Transport } = require('winston-transport');

class PuppeteerTransport extends Transport {
  log(info, callback) {
    // Дополнительная обработка логов
    process.stdout.write(`PUPPETEER LOG: ${info.timestamp} [${info.level}]: ${info.message}\n`);
    callback();
  }
}

logger.add(new PuppeteerTransport({ level: 'info' }));

Такой подход помогает создавать отдельный поток логов для анализа автоматизации, не загромождая основной файл.


Ротация логов и хранение истории

Для длительного тестирования важно сохранять логи с ротацией:

npm install winston-daily-rotate-file
const DailyRotateFile = require('winston-daily-rotate-file');

logger.add(new DailyRotateFile({
  filename: 'logs/test-%DATE%.log',
  datePattern: 'YYYY-MM-DD',
  maxSize: '20m',
  maxFiles: '14d'
}));

Преимущества:

  • Автоматическое создание новых файлов по дате.
  • Ограничение размера файлов.
  • Сохранение истории на заданный период.

Практические рекомендации

  • Использовать info для основных шагов теста, debug для детальной отладки.
  • Логировать исключения и ошибки страниц отдельно.
  • Настраивать отдельные файлы логов для долгосрочных тестов.
  • Использовать временные метки и фильтрацию уровней для удобного анализа.
  • Совмещать стандартные и кастомные транспорты для разделения логов по категориям (например, Puppeteer, API-запросы, вспомогательные скрипты).

Winston обеспечивает гибкое и масштабируемое логирование, которое повышает надежность автоматизированного тестирования Puppeteer и упрощает анализ возникающих проблем.