QA Interview Hub · База знань · Тести

Логи й observability

Логи в автоматизації

Консоль браузера й помилки сторінки в Playwright

E2E-тест може пройти зелено, поки в консолі браузера летять необроблені винятки або 500-ті на фонових запитах. Playwright дозволяє слухати ці події:

  • page.on('console', msg => …) — виклики console.*; msg.type() повертає 'error', 'warning', 'log' тощо, msg.text() — текст;
  • page.on('pageerror', err => …) — необроблені винятки на сторінці;
  • page.on('requestfailed', req => …) — мережеві збої; page.on('response', …) — відповіді (можна відфільтрувати status() >= 500).

Найзручніше загорнути це в авто-фікстуру, щоб правило діяло на всі тести:

import { test as base, expect } from '@playwright/test';

export const test = base.extend<{ browserErrors: string[] }>({
  browserErrors: [
    async ({ page }, use) => {
      const errors: string[] = [];
      page.on('pageerror', (e) => errors.push(e.message));
      page.on('console', (m) => {
        if (m.type() === 'error') errors.push(m.text());
      });
      await use(errors);
      expect(errors, 'unexpected browser errors').toEqual([]);
    },
    { auto: true },
  ],
});

Нюанси:

  • підписку роблять до навігації, інакше ранні помилки пропадуть;
  • потрібен список дозволених винятків (allowlist) для відомого шуму сторонніх скриптів (аналітика, віджети) — інакше тести стануть червоними через те, що команда не контролює; але allowlist має бути вузьким і з коментарем;
  • якщо тест навмисно викликає помилку (негативний сценарій), він очікує її явно, а не вимикає перевірку;
  • помилки конкретного ресурсу (наприклад, 404 на favicon) бувають шумом; фільтрують за URL, а не вимикають усе.

Так фронтенд-регресії ловляться відразу, без окремого тесту «чи немає помилок у консолі».

Серверні логи в CI, перевірка логів у тестах і логування самого тесту

Серверні логи як артефакт CI. Коли e2e падає в CI, одного скріншота мало: потрібні й логи застосунку за той самий час. Підхід: запускати сервіси так, щоб їхній вивід зберігався (docker compose logs --no-color --timestamps > server.log або файл, на який налаштовано логер), а наприкінці джоби завантажити його як артефакт — з умовою, що виконується й після падіння:

- name: Collect service logs
  if: ${{ !cancelled() }}
  run: docker compose logs --no-color --timestamps > server.log
- uses: actions/upload-artifact@v4
  if: ${{ !cancelled() }}
  with:
    name: server-logs
    path: server.log
    retention-days: 7

Щоб зіставити тест із записами, кожен запит тесту несе свій traceparent / X-Request-Id, а його значення додають у звіт (testInfo.annotations.push або testInfo.attach('server-log', { body, contentType: 'text/plain' })).

Перевірка логів у тесті. Інколи потрібно впевнитись, що подія залогована (аудит, безпека, «секрет не потрапив у лог»). Це доречно, коли:

  • лог — частина вимоги (аудит дій, compliance), а не випадковий текст;
  • шукаємо за структурованими полями й унікальним id, а не за підрядком повідомлення;
  • очікування з expect.poll/toPass, бо логи доходять до сховка із затримкою.

Крихко, коли тест перевіряє точне формулювання повідомлення, порядок рядків чи DEBUG-логи: будь-який рефакторинг ламає тест, хоча поведінка не змінилась. Те, що важливо для бізнесу, краще виставляти як подію чи метрику з контрактом.

Логування в самому тесті. Кроки робіть через test.step('…', async () => …) — вони потрапляють у звіт і trace. Дані для діагностики (відповідь API, відповідний уривок лога) додавайте як testInfo.attach. Не залишайте console.log по всьому коду: він засмічує вивід, а в паралельних воркерах рядки перемішуються.

Секрети й PII у логах, шум і retention

Логи читає багато людей і живуть вони довго, тому те, що туди потрапило, витікає. Не можна логувати: паролі, токени (access/refresh, API keys), повні номери карток, CVV, повні тіла запитів автентифікації, а також персональні дані (email, телефон, адреса, документи) — вони підпадають під GDPR та інші регуляції.

Що роблять:

  • Маскування/редагування на рівні логера чи в OTel Collector: Authorization: Bearer ***, картка → **** 4242, email → хеш чи частковий вигляд;
  • логувати ідентифікатор користувача (внутрішній id), а не email чи ім’я;
  • allowlist полів для запитів/відповідей замість «логуємо все, потім видаляємо»;
  • вимкнений DEBUG на проді та контроль доступу до логів.

Роль QA: перевірити (вручну чи автотестом), що після логіну, оплати, скидання пароля чутливі значення не з’являються у логах і в тілі помилок; у CI-логах секрети маскуються (GitHub Actions маскує значення secrets, але не похідні від них, наприклад, закодовані у base64); тестові дані не містять реальних персональних даних.

Шум. Якщо ERROR щодня сотні й ніхто не дивиться, реальну проблему не помітять. Ознаки: очікувані винятки логуються як ERROR (наприклад, «користувача не знайдено» при невірному логіні); один і той самий запис тисячі разів на секунду; health-check спамить INFO. Рішення: правильні рівні, дедуплікація, семплінг, винесення помилок у трекер із групуванням.

Retention. Логи зберігають обмежений час (діб, тижнів) — через вартість і вимоги приватності; аудит-логи можуть мати довший строк. Для QA це означає: артефакти й логи зі збійного прогону слід вичитати чи зберегти, поки вони не зникли; у баг-репорт вкладайте уривок, а не посилання на запис, який видалиться.