Какие используешь принципы тестирования

Ответ

Принципы тестирования, которые я применяю:

  1. Изолированность тестов - каждый тест должен быть независимым и не влиять на другие. Использую beforeEach, afterEach для подготовки/очистки.

  2. Тестирование поведения, а не реализации - фокус на том, что делает компонент, а не как он устроен внутри.

  3. Пирамида тестов - больше юнит-тестов, меньше интеграционных, ещё меньше E2E.

  4. Читаемость тестов - применяю паттерн AAA (Arrange-Act-Assert):

test('should increment counter', () => {
  // Arrange
  const { getByText } = render(<Counter />);

  // Act
  fireEvent.click(getByText('Increment'));

  // Assert
  expect(getByText('Count: 1')).toBeInTheDocument();
});
  1. Тестирование граничных случаев - пустые данные, ошибки API, крайние значения.

  2. Моки и стабы - для изоляции тестируемого модуля от зависимостей.

  3. Тестирование доступности - проверка, что компонент работает с screen readers.

Ответ 18+ 🔞

А, ну ты глянь, какие принципы тестирования у меня в арсенале, блядь! Слушай сюда, распишу, как я это дело организую, чтобы потом не орать "ой, бля, всё сломалось, пиздец".

Первое, и это святое, блядь — изолированность тестов. Каждый тест — это как отдельный, ёпта, монах в келье. Никаких связей, никаких побочных эффектов от соседа. Для этого я юзаю beforeEach и afterEach. Перед каждым тестом — подготовил чистенькую песочницу, поиграл, а после — всё за собой убрал, хули мусорить-то. Чтобы один тест, словив ошибку, не потащил за собой всех остальных, как цепная реакция, нахуй.

Второе — тестируем поведение, а не внутренности. Это ж как с человеком: мне похуй, как у тебя там кишки устроены, главное — чтобы ты не срал в лифте. Вот и с компонентом так же. Меня волнует, что он показывает пользователю и как реагирует на клики, а не то, какие там хуёвые переменные внутри крутятся. Реализацию поменяешь — и ничего, тесты должны остаться зелёными, если поведение-то то же самое.

Третье — пирамида тестов, мать её. Основание, толстое и надёжное — это юнит-тесты. Их дохуя, они быстрые, дешёвые. Потом, поменьше — интеграционные. Ну а на самом верху, штучно — E2E, эти жирные, медленные звери. Если пирамиду перевернуть и пытаться стоять на верхушке — она тебе на голову и рухнет, вместе со всеми дедлайнами, блядь.

Четвёртое — читаемость, ёбана. Чтобы через месяц не смотреть на свой же тест и не спрашивать "чё это за хуйню я тут написал?". Для этого есть паттерн AAA: Arrange-Act-Assert. Разложил, как на блюдечке. Смотри, вот тебе примерчик:

test('should increment counter', () => {
  // Arrange — расчехлили всё, что нужно
  const { getByText } = render(<Counter />);

  // Act — сделали то самое действие, которое проверяем
  fireEvent.click(getByText('Increment'));

  // Assert — проверили, что получили ожидаемый пиздец
  expect(getByText('Count: 1')).toBeInTheDocument();
});

Всё, как в аптеке. Никакой магии, никакой ебалы.

Пятое — граничные случаи. Это где всё обычно и ломается, сука. Пустой массив пришёл? Ошибка от API? Пользователь ввёл "9999999", когда максимум "5"? Вот на это и надо давить, в эти самые слабые места. Если компонент выживает после этого — значит, мужик, блядь, крепкий.

Шестое — моки и стабы. Это когда твой компонент зависит от какого-то внешнего сервиса, который сегодня работает, а завтра — хуй с горы. Мы его заменяем на послушную заглушку, которая всегда отвечает то, что нам надо для теста. Полная изоляция, никаких сюрпризов.

Ну и седьмое, про что многие забывают, — тестирование доступности. А вдруг твой интерфейс будут смотреть не глазами, а, блядь, слухом? Screen reader должен понимать, что к чему. Проверить это — дело святое, а то получится история про Герасима и Муму, только в роли немого — твой пользователь.

Вот так вот, коротко и по делу. Без этой дисциплины — один сплошной "вротберунчик" и дебаг до пяти утра. А оно тебе надо?