QA Interview Hub · База знань · Тести
Cypress
Основи й архітектура
як влаштований фреймворк
Що таке Cypress і чим він відрізняється від Selenium?
Cypress — фреймворк для end-to-end і компонентного тестування вебзастосунків на JavaScript або TypeScript.
Головна різниця в тому, де живе тест. Selenium керує браузером ззовні через WebDriver: кожна команда — окремий HTTP-запит до драйвера. Cypress виконує тест усередині браузера, в тій самій вкладці, що й застосунок.
Звідси переваги: прямий доступ до DOM і window, автоматичні очікування, time-travel по кроках у Test Runner і вбудований перехоплювач мережі. Під капотом Cypress використовує Mocha для структури тестів (describe, it, хуки), Chai для асертів і Sinon для cy.stub, cy.spy і cy.clock.
На співбесіді: Cypress — це фреймворк для e2e і компонентного тестування на JavaScript. Головна відмінність від Selenium в архітектурі: Selenium керує браузером ззовні через WebDriver, де кожна команда — окремий HTTP-запит, а Cypress виконує тести прямо в браузері, поруч із застосунком. Тому він має прямий доступ до DOM, сам чекає на елементи, дає time-travel для дебагу й уміє перехоплювати мережу. Всередині він побудований на Mocha, Chai і Sinon.
А в Playwright:Playwright теж обходиться без WebDriver, але працює протилежно до Cypress: керує браузером ззовні через одне постійне з'єднання і рідний протокол браузера (CDP для Chromium, патчені протоколи для Firefox і WebKit). Тести можна писати не лише на JS/TS, а й на Python, Java і .NET.
Як влаштована архітектура Cypress під капотом?
Cypress складається з двох частин, які постійно спілкуються.
- Node-процес. Запускає браузер, працює як проксі для всього HTTP-трафіку сторінки, виконує
cy.task (файли, база даних), робить скріншоти й відео.
- Браузер. Сторінка Cypress містить два iframe: spec iframe з твоїм тестовим кодом і app iframe із застосунком. Оскільки вони в одній вкладці, тест бачить DOM застосунку напряму, без протоколу посередині.
Між Node-процесом і браузером — WebSocket. Саме проксі в Node дає змогу cy.intercept бачити і підміняти кожен запит.
┌──────────── Браузер (одна вкладка) ────────────┐
│ spec iframe │ app iframe │
│ тест + черга cy │ застосунок │
│ прямий доступ до DOM ──┼──► │
└──────────────┬──────────────────────────────────┘
│ WebSocket + HTTP через проксі
┌──────────────▼──────────────────────────────────┐
│ Node-процес Cypress │
│ проксі (cy.intercept) · cy.task · файли · відео│
└─────────────────────────────────────────────────┘
На співбесіді: Cypress працює як два процеси. Перший — Node-процес: він запускає браузер, пропускає через себе весь мережевий трафік як проксі й виконує все, чого не вміє браузер, наприклад роботу з файлами чи базою через cy.task. Другий — сам браузер, де в одній вкладці живуть два iframe: в одному мій тест, у другому застосунок. Тому тест має прямий доступ до DOM. Між Node і браузером — WebSocket, а саме проксі дає змогу перехоплювати запити через cy.intercept.
А в Playwright:У Playwright немає iframe з тестом поруч із застосунком. Тест живе в Node, Playwright-сервер шле команди браузеру через протокол. Тому тест не має прямого доступу до DOM (лише через page.evaluate), зате без обмежень працює з кількома вкладками, доменами й контекстами.
Чим cypress open відрізняється від cypress run?
cypress open відкриває інтерактивний Test Runner: вибираєш спек, бачиш кожну команду, можеш повернутися до будь-якого кроку (time-travel), а тест перезапускається після збереження файлу. Це режим для написання й дебагу.
cypress run запускає тести без інтерфейсу, за замовчуванням headless в Electron, з виводом у консоль і скріншотами при падінні. Це режим для CI.
npx cypress open # інтерактивно
npx cypress run # headless, Electron
npx cypress run --browser chrome # конкретний браузер
npx cypress run --spec "cypress/e2e/login.cy.ts"
npx cypress run --headed # з вікном браузера
На співбесіді: Open — це інтерактивний режим для розробки: я бачу кожну команду, можу повернутися до будь-якого кроку і тест перезапускається при збереженні. Run — це headless-запуск для CI: без інтерфейсу, з виводом у консоль і скріншотами при падінні. У run можна вказати браузер, конкретний спек або запустити в headed-режимі.
А в Playwright:Аналог — npx playwright test, headless за замовчуванням. Замість Test Runner є --ui (UI mode з таймлайном і DOM-знімками), --debug з інспектором і --headed. Браузери обирають через --project, а не --browser.
Як виглядає структура проєкту і конфіг Cypress?
З версії 10 конфіг живе у файлі cypress.config.js або .ts. Старий cypress.json більше не використовується — якщо згадаєш його як поточний, це видасть застарілі знання.
Типова структура: cypress/e2e для тестів, cypress/fixtures для тестових даних, cypress/support для кастомних команд і глобальних налаштувань.
// cypress.config.ts
import { defineConfig } from 'cypress';
export default defineConfig({
e2e: {
baseUrl: 'https://staging.example.com',
specPattern: 'cypress/e2e/**/*.cy.ts',
defaultCommandTimeout: 6000,
retries: { runMode: 2, openMode: 0 },
setupNodeEvents(on, config) {
// cy.task, плагіни, звіти
return config;
},
},
});
// cypress/
// e2e/ тести *.cy.ts
// fixtures/ JSON з тестовими даними
// support/
// e2e.ts виконується перед кожним спеком
// commands.ts кастомні команди
На співбесіді: Починаючи з десятої версії конфіг пишеться у cypress.config.ts через defineConfig, з окремими блоками для e2e і component testing. Там задаються baseUrl, шаблон пошуку спеків, таймаути, retries і setupNodeEvents для Node-логіки. Тести лежать у папці e2e, тестові дані — у fixtures, а кастомні команди й глобальні налаштування — у support.
А в Playwright:Конфіг — playwright.config.ts. Замість окремих блоків e2e і component там projects: різні браузери, девайси, setup-проєкт для логіну. Папки support немає: спільна логіка живе у фікстурах через test.extend.
Чим e2e-тести відрізняються від component testing у Cypress?
E2E відкриває весь застосунок через cy.visit і проходить сценарій як користувач, з реальним бекендом або моками мережі.
Component testing монтує один компонент React, Vue чи Angular через cy.mount у справжньому браузері, без решти застосунку. Це швидко й ізольовано: зручно перевіряти стани кнопки, форми чи таблиці з різними props, не піднімаючи весь фронтенд.
// component test
import { PriceTag } from './PriceTag';
it('показує знижку', () => {
cy.mount(<PriceTag price={100} discount={20} />);
cy.get('[data-cy=final-price]').should('have.text', '80');
});
На співбесіді: E2E-тест відкриває весь застосунок і проходить сценарій як користувач. Component testing монтує окремий компонент через cy.mount у справжньому браузері, без решти застосунку і без бекенду. Це набагато швидше і зручно для перевірки різних станів компонента, а e2e лишається для ключових наскрізних сценаріїв.
А в Playwright:У Playwright component testing досі експериментальний (@playwright/experimental-ct-react та аналоги). Для компонентних тестів Cypress зараз зріліший.
Архітектура Cypress і порівняння
Cypress виконує тести всередині браузера, в тому ж run loop, що й застосунок, а поруч працює Node.js-процес для задач поза браузером. Selenium і Playwright керують браузером ззовні: Selenium через WebDriver, Playwright через CDP та власні протоколи. Через таку архітектуру Cypress має прямий доступ до DOM, window і мережевих запитів застосунку.
Переваги: зручний інтерактивний раннер з time-travel знімками кожного кроку, вбудовані ретраї й очікування, простий старт, cy.intercept для мережі, component testing. Обмеження: лише JavaScript/TypeScript, одна вкладка, складніша робота з iframe та кількома доменами, немає підтримки Safari (лише експериментальний WebKit).
Playwright швидший, має вбудовану паралелізацію без платного сервісу, кілька вкладок і контекстів, мови крім JS. Паралелізація в Cypress можлива, але зазвичай через Cypress Cloud або сторонні рішення на кшталт шардингу в CI.