Основные рекомендации

  • Когда это возможно, пишите функции (или компоненты React), которые являются как можно более «чистыми» (функции, которые производят вывод из ввода без побочных эффектов), потому что их легче тестировать.
  • Используйте насмешки, чтобы изолировать модульные тесты, но когда насмешка для теста кажется более сложной, чем тестируемый код, вы можете пересмотреть структуру своего кода или изучить альтернативные стратегии тестирования.
  • Как минимум используйте подход в стиле TDD при исправлении ошибок. Напишите неудачный тест, примените предполагаемое исправление ошибки и убедитесь, что тесты пройдены.
  • Включите покрытие кода в свой CI, но не стремитесь к 100% покрытию и не думайте, что это означает, что ваш код хорошо протестирован.

Преимущества написания тестов

  • Тесты помогают предотвратить регрессию
  • Тесты служат живой документацией того, что должен делать ваш код, и могут быть очень полезны для тех, кто подключается к вашему проекту, или пользователей вашего кода.
  • Написание тестов заставляет вас как разработчика понять, каково ожидаемое поведение вашего кода, и может помочь определить потенциальные возможности для рефакторинга.

Модульные тесты

  • Модульные тесты оценивают поведение отдельной единицы кода. Наиболее очевидным примером модульного теста является код, который проверяет поведение одной функции, но эта единица может быть функцией, классом, компонентом React и многим другим.
  • Примеры: тесты компонентов React (Enzyme), JUnit (Java), unittest (Python).

Интеграционные тесты

  • Интеграционные тесты оценивают поведение и взаимодействие нескольких единиц кода или уровней программного обеспечения. Смысл интеграционных тестов в том, чтобы убедиться, что ваше программное обеспечение ведет себя так, как ожидается, когда несколько единиц кода или слоев фактически взаимодействуют друг с другом.
  • Интеграционные тесты имеют решающее значение, потому что вполне возможно (и часто) иметь каждую отдельную единицу кода, прошедшую тесты, но эти единицы кода не будут вести себя должным образом при интеграции вместе
  • Интеграционные тесты не должны проверять интеграцию всех ваших программных компонентов. У вас может быть интеграционный тест, который проверяет только интеграцию между двумя модулями кода или слоями программного обеспечения.
  • Примеры: браузерные тесты Cypress, поведенческие тесты, Jasmine (Javascript).

Использование насмешек в тестах

  • Мокирование обеспечивает изоляцию ваших тестов и позволяет убедиться, что вы тестируете поведение своего кода, а не зависимости, используемые вашим кодом.
  • Имитация поведения в крайних случаях (например, имитация метода зависимости для выдачи неожиданной ошибки)
  • Примеры: имитация уровня API или ответов для ваших интерфейсных тестов, имитация ответов из внешних библиотек/кода в модульных тестах.
  • Ключевой вопрос. Если этот тест не пройден, что можно исправить? Если ответ когда-либо будет «не в этой функции» или «не в этой службе», то вы можете подумать о том, чтобы смоделировать эту зависимость для теста, иначе успех вашего теста, по крайней мере, частично зависит от этой внешней функции/службы.

Сколько тестов мне нужно?

  • Покрытие кода полезно для получения приблизительного представления о том, сколько строк вашего кода тестируется, но объем покрытия ничего не говорит о качестве этих тестов. Таким образом, использование 100% в качестве цели для обеспечения «хорошего тестирования» вашего проекта может ввести в заблуждение. 70% покрытие кода часто упоминается как хорошая цель для проекта, но в этом конкретном числе нет ничего волшебного.
  • Есть несколько методологий тестирования, которые пытаются предписать, сколько модульных тестов вы должны написать, например Структурированное базовое тестирование.

Когда писать тесты

  • Классическая разработка через тестирование (TDD). Пишите тесты по мере разработки кода. Преимущество этого подхода в том, что он заставляет вас заранее думать о поведении вашего кода и поощряет вас писать тестируемый код с самого начала.
  • Вы также можете использовать упрощенный TDD-подход при диагностике ошибок: написать тест, который воспроизводит ошибку, применить ожидаемое исправление, а затем убедиться, что тест проходит. Такой подход дает вам уверенность в том, что ваши изменения действительно устранили ошибку.