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-сервис |
Практическое упражнение
- Создайте проект Playwright Test, который тестирует публичный веб-сайт (например, https://demo.playwright.dev/todomvc/)
- Напишите тесты для: добавления задачи, завершения задачи, фильтрации активных/завершённых
- Добавьте интерфейсы TypeScript для данных ответов API
- Используйте фикстуры для общей настройки (предзаполненный список задач)
Ключевые выводы
- TypeScript добавляет типобезопасность, которая ловит ошибки в тестах на этапе компиляции
- Jest для модульных/API-тестов, Playwright для E2E, Cypress для компонентных + E2E
- Изучите хотя бы один фреймворк глубоко; уметь читать код на остальных
- Используйте атрибуты data-testid для надёжного выбора элементов
- Автоматическое ожидание в Playwright устраняет большинство нестабильностей в E2E-тестах