Как сделать качественный End-to-end тест

Ответ

Качественный E2E тест должен проверять реальные пользовательские сценарии, быть стабильным и быстрым. Основные принципы:

  1. Тестируй ключевые сценарии - авторизация, основные CRUD-операции
  2. Используй реалистичные данные - но не зависи от них (можно мокать)
  3. Избегай хрупких селекторов - вместо div.button используй data-testid
  4. Добавляй ожидания - но не sleep(), а явные ожидания элементов

Пример на Cypress:

describe('Login flow', () => {
  it('successfully logs in', () => {
    cy.visit('/login')
    cy.get('[data-testid="email"]').type('user@example.com')
    cy.get('[data-testid="password"]').type('password123')
    cy.get('[data-testid="submit"]').click()
    cy.url().should('include', '/dashboard')
  })
})

Дополнительно:

  • Запускай тесты в CI/CD
  • Используй снэпшоты для проверки UI
  • Изолируй тесты друг от друга
  • Логируй шаги для отладки

Ответ 18+ 🔞

Ага, слушай, вот тебе про E2E тесты, но без этой офисной зауми, как есть. Представь, что ты пытаешься доказать, что твой сайт не развалится, когда на него зайдёт первый живой пользователь, а не ты, пьяный, в три ночи.

Первое, и главное, блядь. Не надо пытаться проверить ВСЁ. Это как пытаться протестировать машину, залезая в неё через багажник и вылезая через люк. Бери ключевые сценарии, от которых у пользователя реально пиздец случится, если они сломаются. Авторизация, оплата, добавление товара в корзину — вот это вот всё. Если кнопка «лайкнуть котика» не работает — мир не рухнет, потерпит.

Второе. Данные. Ты же не будешь на проде тесты гонять, да? Вот и не завись от них. Подсовывай свои, красивые и предсказуемые. Но чтобы они были похожи на правду. Не «asdasd@asdasd.com», а что-то вроде «test.user@example.com». Чувство прекрасного, ёпта!

Третье, и это овердохуища важно. Селекторы. Если ты цепляешься за div.button:nth-child(3) > span, то ты, прости, пидарас шерстяной. Дизайнер чихнёт — и твой тест накроется медным тазом. Используй data-testid. Это как метка «ломать нельзя» для твоего кода. Дизайн меняется — селектор остаётся. Красота.

Четвёртое. Ожидания. Твой тест не должен тупо спать, как сурок, sleep(5000). Это признак того, что терпения ноль ебать. Используй явные ожидания: «жди, пока эта хрень появится на странице». Цикл «проверил — не появилось — подождал — проверил». Браузеры и сети — существа нестабильные, будь готов к этому.

Вот, смотри, как это выглядит в деле, на примере этого самого Cypress:

describe('Логин, чтобы не опозориться', () => {
  it('таки успешно логинится', () => {
    // Приехали на страницу логина
    cy.visit('/login')
    // Тыкаем в поле для мыла. DATA-TESTID, Карл!
    cy.get('[data-testid="email"]').type('normalny.user@example.com')
    // Вводим пароль. Не "123", конечно.
    cy.get('[data-testid="password"]').type('normParol123')
    // БАЦ по кнопке!
    cy.get('[data-testid="submit"]').click()
    // И теперь ЖДЁМ, ОЖИДАЕМ, а не спим. Проверяем, что нас унесло на дашборд.
    cy.url().should('include', '/dashboard')
  })
})

А теперь, бонусом, что ещё крутить:

  • Гоняй это в CI/CD. Чтобы, когда какой-нибудь гений заливает свою «фичу», вся пачка тестов ему тут же в ебальник прилетала. Автоматически. Волнение ебать сразу видно.
  • Снэпшоты — твои друзья. Сделал скриншот важной страницы. После изменений — сравнили. Если поплыло не там, где надо — тревога. Хуй с горы, если кнопка на 2 пикселя съехала, но если половина текста исчезла — это пиздец.
  • Изолируй тесты. Каждый тест должен начинать жизнь с чистого листа. Чтобы падение одного не потянуло за собой всех, как домино. Иначе доверия ебать ноль ко всему прогону.
  • Логируй. Если тест сдох, ты должен понять ГДЕ и ПОЧЕМУ, а не гадать на кофейной гуще. «Нажал на кнопку — ок», «перешёл на страницу — ок», «элемент не найден — всё, пизда». Отладка в разы быстрее.

Вот и вся философия. Не надрочиться на 100% покрытие, а сделать так, чтобы основные сценарии работали крепко, и ты мог спать спокойно. Ну, или хотя бы не так тревожно.