← Назад к вопросам

Добавляешь ли что-либо для тестирования в приложение

2.0 Middle🔥 161 комментариев
#JavaScript Core

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI2 апр. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Добавление кода для тестирования: Best Practices

Да, при разработке фронтенда я добавляю специальный код, чтобы облегчить тестирование. Это нормальная практика, которая ускоряет как разработку, так и автоматизацию тестов.

1. Data Attributes для селекторов в тестах

Зачем: Тестовые фреймворки (Playwright, Cypress, Testing Library) нужны селекторы для поиска элементов. Вместо хрупких селекторов по классам CSS используем специальные атрибуты.

// Плохо — селектор зависит от CSS класса
const button = document.querySelector('.primary-button.lg');
// Если дизайнер изменит класс, тест сломается

// Хорошо — используем data-testid
<button data-testid="submit-button" className="primary-button lg">
  Отправить
</button>

// Тест
test('submit button works', async ({ page }) => {
  const button = page.getByTestId('submit-button');
  await button.click();
});

2. Test ID Constants

Для больших приложений создаём файл с константами тестовых ID:

// constants/testIds.ts
export const TEST_IDS = {
  auth: {
    emailInput: 'auth-email-input',
    passwordInput: 'auth-password-input',
    loginButton: 'auth-login-button',
    logoutButton: 'auth-logout-button',
  },
  questions: {
    questionCard: 'question-card',
    answerButton: 'answer-button',
    filterSelect: 'filter-select',
  },
  common: {
    loader: 'common-loader',
    errorMessage: 'common-error-message',
    successMessage: 'common-success-message',
  },
} as const;

3. Role-based Селекторы (Accessibility)

Это лучше чем data-testid, так как тестирует и accessibility:

// Отлично — используем role
<button role="button" aria-label="Отправить форму">
  Отправить
</button>

// Тест
test('submit button', async ({ page }) => {
  const button = page.getByRole('button', { name: 'Отправить форму' });
  await button.click();
});

// Другие роли
const input = page.getByRole('textbox', { name: 'Email' });
const select = page.getByRole('combobox');
const heading = page.getByRole('heading', { level: 1 });

4. Testing Library в Unit Тестах

Unit тесты с Testing Library:

import { render, screen } from '@testing-library/react';
import { LoginForm } from './LoginForm';

test('renders login form', () => {
  render(<LoginForm onSubmit={() => {}} />);
  
  // Лучше: по role (тестирует accessibility)
  const emailInput = screen.getByRole('textbox', { name: /email/i });
  expect(emailInput).toBeInTheDocument();
  
  // Альтернатива: по testid
  const submitButton = screen.getByTestId('login-button');
  expect(submitButton).toBeInTheDocument();
});

5. Mock Data и Fixtures

Для тестирования создаём фиксчуры с тестовыми данными:

// fixtures/mockData.ts
export const mockUser = {
  id: '1',
  name: 'John Doe',
  email: 'john@example.com',
  role: 'admin',
};

export const mockQuestions = [
  { id: '1', title: 'What is React?', difficulty: 'easy' },
  { id: '2', title: 'What is Hook?', difficulty: 'medium' },
];

// В тесте
test('render questions list', () => {
  render(<QuestionsList questions={mockQuestions} />);
  expect(screen.getByText('What is React?')).toBeInTheDocument();
});

6. Environment-specific Code

Некоторый код нужен только для тестирования:

// Добавляем глобальный объект только в тестах
if (process.env.NODE_ENV === 'test') {
  (window as any).__TEST_DATA__ = {
    users: [
      { id: 1, name: 'Test User' },
    ],
  };
}

// Используем в тестах
test('user data', () => {
  const testData = (window as any).__TEST_DATA__;
  expect(testData.users).toHaveLength(1);
});

7. API Mocking

Для тестов мокируем API запросы:

// Используем MSW (Mock Service Worker)
import { http, HttpResponse } from 'msw';
import { setupServer } from 'msw/node';

const server = setupServer(
  http.get('/api/v1/user', () => {
    return HttpResponse.json({ id: '1', name: 'John' });
  })
);

beforeAll(() => server.listen());
afterEach(() => server.resetHandlers());
afterAll(() => server.close());

test('fetch user', async () => {
  const response = await fetch('/api/v1/user');
  const data = await response.json();
  expect(data.name).toBe('John');
});

8. React Component Testing

export function LoginForm({ onSubmit }: { onSubmit: (data: any) => void }) {
  const [email, setEmail] = useState('');

  return (
    <form onSubmit={(e) => {
      e.preventDefault();
      onSubmit({ email });
    }}>
      <input
        type="email"
        value={email}
        onChange={(e) => setEmail(e.target.value)}
        data-testid="email-input"
        placeholder="Email"
      />
      <button type="submit" data-testid="login-button">Login</button>
    </form>
  );
}

Тест:

test('login form submission', async () => {
  const handleSubmit = vi.fn();
  const { getByTestId } = render(<LoginForm onSubmit={handleSubmit} />);
  
  const emailInput = getByTestId('email-input');
  const submitButton = getByTestId('login-button');
  
  await userEvent.type(emailInput, 'user@example.com');
  await userEvent.click(submitButton);
  
  expect(handleSubmit).toHaveBeenCalledWith({
    email: 'user@example.com',
  });
});

9. Что НЕ нужно добавлять

Не добавляй:

  • console.log для debug
  • Комментарии "TODO: remove for production"
  • Хардкодированные тестовые значения в production коде
  • Дополнительные зависимости только для тестов в production сборке

Добавляй только:

  • data-testid и aria-* для доступности
  • Mock функции и фиксчуры
  • Test-специфичный код за флагом process.env.NODE_ENV

10. Best Practices

ПрактикаХорошоПлохо
Селекторыdata-testid или roleclassName, id (хрупкие)
ConstantsЦентрализованные TEST_IDSСтроки в коде
Mock DataFixtures в отдельном файлеПрямо в тестах
DebugТолько для developmentВ production коде
Environmentprocess.env.NODE_ENVХардкод условий

На собеседовании

Полный ответ должен показать:

  • Понимание разницы — что добавлять, что нет
  • Data-testid практика — как делать селекторы стабильными
  • Accessibility-first — использовать role когда возможно
  • Организация кода — constants, fixtures, mocks
  • Опыт с фреймворками — Playwright, Testing Library, Vitest
Добавляешь ли что-либо для тестирования в приложение | PrepBro