Modern QA2026JavaScript и TypeScript для QA
Join

Course12 Programming for QA

Foundations · Chapter 12

JavaScript и TypeScript для QA

Updated Jul 2026

JavaScript доминирует в тестировании фронтенда, а TypeScript добавляет типобезопасность, необходимую крупным тест-сьютам. Если тестируемое приложение построено на React, Vue, Angular или Node.js, ваш тестовый фреймворк почти наверняка будет основан на JavaScript или TypeScript.

Почему JavaScript/TypeScript для QA

Аспект JavaScript TypeScript
Тестовые фреймворки Jest, Mocha, Playwright Test, Cypress Те же, с проверкой типов
Автоматизация браузера Selenium, Playwright, Cypress, Puppeteer Те же, с автодополнением
Тестирование API axios, fetch, supertest Те же, с типизированными ответами
Где доминирует Тестирование фронтенда, E2E-тестирование, full-stack приложения То же, с лучшей поддерживаемостью
Кривая обучения Ниже Немного выше (типы)

Преимущество TypeScript для QA

TypeScript ловит ошибки на этапе компиляции, которые иначе стали бы нестабильными тестами во время выполнения:

// Without TypeScript: this bug is found at runtime (maybe)
const userName = response.data.user.nme;  // typo: should be "name"

// With TypeScript: this bug is found immediately in your editor
interface User {
    id: number;
    name: string;
    email: string;
}
const user: User = response.data;
const userName = user.nme;  // TypeScript error: Property 'nme' does not exist

Jest: модульное и интеграционное тестирование

Jest — самый популярный тестовый фреймворк для JavaScript. Он обычно используется для модульных тестов, тестов API и компонентных тестов.

// user.test.ts
describe("User API", () => {
    let authToken: string;

    beforeAll(async () => {
        const response = await fetch(`${BASE_URL}/auth/login`, {
            method: "POST",
            headers: { "Content-Type": "application/json" },
            body: JSON.stringify({ email: "test@example.com", password: "pass123" })
        });
        const data = await response.json();
        authToken = data.access_token;
    });

    test("GET /users/me returns current user", async () => {
        const response = await fetch(`${BASE_URL}/users/me`, {
            headers: { Authorization: `Bearer ${authToken}` }
        });
        expect(response.status).toBe(200);

        const user = await response.json();
        expect(user).toHaveProperty("id");
        expect(user).toHaveProperty("email", "test@example.com");
        expect(user).not.toHaveProperty("password");
    });

    test("GET /users/me without auth returns 401", async () => {
        const response = await fetch(`${BASE_URL}/users/me`);
        expect(response.status).toBe(401);
    });
});

Матчеры Jest для QA

// Equality
expect(status).toBe(200);                    // strict equality
expect(user).toEqual({ id: 1, name: "Alice" }); // deep equality

// Truthiness
expect(token).toBeDefined();
expect(error).toBeNull();
expect(items.length).toBeTruthy();

// Numbers
expect(responseTime).toBeLessThan(1000);
expect(items.length).toBeGreaterThanOrEqual(1);

// Strings
expect(message).toMatch(/success/i);
expect(url).toContain("/api/v1");

// Arrays and Objects
expect(roles).toContain("admin");
expect(user).toHaveProperty("email");
expect(errors).toHaveLength(0);

Playwright Test: E2E-тестирование

Playwright Test — современный стандарт для сквозного тестирования в браузере в экосистеме JS/TS.

// checkout.spec.ts
import { test, expect } from '@playwright/test';

test.describe("Checkout Flow", () => {
    test("user can complete purchase", async ({ page }) => {
        await page.goto("/products");
        await page.click('[data-testid="add-to-cart"]');
        await expect(page.locator(".cart-count")).toHaveText("1");

        await page.click('[data-testid="checkout-button"]');
        await page.fill('[name="card-number"]', "4111111111111111");
        await page.fill('[name="expiry"]', "12/25");
        await page.fill('[name="cvv"]', "123");
        await page.click('[data-testid="pay-button"]');

        await expect(page.locator(".confirmation")).toContainText("Order confirmed");
    });

    test("empty cart shows appropriate message", async ({ page }) => {
        await page.goto("/cart");
        await expect(page.locator(".empty-cart-message")).toBeVisible();
        await expect(page.locator('[data-testid="checkout-button"]')).toBeDisabled();
    });
});

Фикстуры Playwright

// fixtures.ts
import { test as base } from '@playwright/test';

type TestFixtures = {
    authenticatedPage: Page;
};

export const test = base.extend<TestFixtures>({
    authenticatedPage: async ({ page }, use) => {
        await page.goto("/login");
        await page.fill('[name="email"]', "test@example.com");
        await page.fill('[name="password"]', "pass123");
        await page.click('[type="submit"]');
        await page.waitForURL("/dashboard");
        await use(page);
    },
});

Cypress: компонентное и E2E-тестирование

Cypress работает в браузере вместе с вашим приложением, что даёт уникальные возможности для тестирования фронтенда.

// checkout.cy.ts
describe("Checkout Flow", () => {
    beforeEach(() => {
        cy.login("test@example.com", "pass123");  // custom command
    });

    it("should complete purchase with valid payment", () => {
        cy.visit("/products");
        cy.get('[data-testid="add-to-cart"]').first().click();
        cy.get(".cart-count").should("have.text", "1");

        cy.get('[data-testid="checkout-button"]').click();
        cy.get('[name="card-number"]').type("4111111111111111");
        cy.get('[data-testid="pay-button"]').click();

        cy.get(".confirmation").should("contain", "Order confirmed");
    });

    it("should intercept and mock payment API", () => {
        cy.intercept("POST", "/api/payments", {
            statusCode: 200,
            body: { status: "success", transaction_id: "mock-123" }
        }).as("payment");

        // ... trigger payment
        cy.wait("@payment");
    });
});

Управление пакетами

Инструмент Lock-файл Скорость Лучше всего для
npm package-lock.json Стандартная Выбор по умолчанию, поставляется с Node.js
yarn yarn.lock Быстрая Монорепозитории, workspaces
pnpm pnpm-lock.yaml Самая быстрая Экономия дискового пространства, строгое разрешение зависимостей
# Initialize and install
npm init -y
npm install --save-dev jest @types/jest ts-jest typescript
npm install --save-dev @playwright/test
npm install --save-dev cypress

Конфигурация TypeScript для тестовых проектов

// tsconfig.json
{
    "compilerOptions": {
        "target": "ES2020",
        "module": "commonjs",
        "strict": true,
        "esModuleInterop": true,
        "outDir": "./dist",
        "rootDir": "./src",
        "types": ["jest", "node"]
    },
    "include": ["src/**/*", "tests/**/*"]
}

Выбор между фреймворками

Фактор Jest Playwright Test Cypress
Тип тестов Модульные, интеграционные, API E2E, автоматизация браузера E2E, компонентные
Выполнение Процесс Node.js Внешнее управление браузером Внутри браузера
Скорость Быстрая (без браузера) Средняя (запуск браузера) Средняя (запуск браузера)
Мокирование сети Ручное (nock, msw) Встроенный route() Встроенный intercept()
Отладка Стандартный отладчик Node Trace viewer, скриншоты Time travel, DOM-снимки
Интеграция с CI Простая Встроенные reporters Dashboard-сервис

Практическое упражнение

  1. Создайте проект Playwright Test, который тестирует публичный веб-сайт (например, https://demo.playwright.dev/todomvc/)
  2. Напишите тесты для: добавления задачи, завершения задачи, фильтрации активных/завершённых
  3. Добавьте интерфейсы TypeScript для данных ответов API
  4. Используйте фикстуры для общей настройки (предзаполненный список задач)

Ключевые выводы

  • TypeScript добавляет типобезопасность, которая ловит ошибки в тестах на этапе компиляции
  • Jest для модульных/API-тестов, Playwright для E2E, Cypress для компонентных + E2E
  • Изучите хотя бы один фреймворк глубоко; уметь читать код на остальных
  • Используйте атрибуты data-testid для надёжного выбора элементов
  • Автоматическое ожидание в Playwright устраняет большинство нестабильностей в E2E-тестах