Тестировать или не тестировать, техническая перспектива

Определите, что вам необходимо проверить, а что можно исключить.

В предыдущей статье были рассмотрены основы тестовых случаев и то, что они должны содержать. В этой статье более подробно рассматривается создание тестовых случаев с технической точки зрения, подробно описывается, что должно быть включено в каждый тест и чего следует избегать. По сути, вы узнаете ответ на извечные вопросы «Что тестировать» или «Что не тестировать».

Что тестировать или не тестировать.

Общие рекомендации и шаблоны

Стоит отметить, что определенные шаблоны и точки имеют решающее значение, независимо от того, проводите ли вы модульные, интеграционные или сквозные тесты. Эти принципы могут и должны применяться к обоим типам тестирования, поэтому они являются хорошей отправной точкой.

Будьте проще

Когда дело доходит до написания тестов, одна из самых важных вещей, которую нужно помнить, — это простота. Важно учитывать возможности мозга. Основной производственный код занимает значительное место, оставляя мало места для дополнительной сложности. Это особенно актуально для тестирования.

Если свободного пространства меньше, вы можете расслабиться в своих усилиях по тестированию. Вот почему крайне важно отдавать приоритет простоте в тестировании. Фактически, лучшие практики тестирования JavaScript Йони Голдберга подчеркивают важность Золотого правила — ваш тест должен ощущаться как помощник, а не как сложная математическая формула. Другими словами, вы должны быть в состоянии понять цель вашего теста с первого взгляда.

Не усложняйте тесты, они не должны быть такими.

Вы должны стремиться к простоте во всех типах тестов, независимо от их сложности. Фактически, чем сложнее тест, тем важнее его упростить. Один из способов добиться этого — использовать плоский дизайн теста, где тесты максимально просты и тестировать только то, что необходимо. Это означает, что каждый тест должен содержать только один тестовый случай, и тестовый случай должен быть сосредоточен на тестировании одной конкретной функциональности или функции.

Подумайте об этом с этой точки зрения: должно быть легко определить, что пошло не так, при чтении проваленного теста. Вот почему важно, чтобы тесты были простыми и понятными. Это позволит вам быстро выявлять и устранять проблемы, когда они возникают.

Проверьте, что того стоит

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

Не проверяйте все подряд.

Не проверяйте детали реализации

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

Ложные отрицательные результаты возникают, когда тест не пройден, даже если тестируемый код корректен. Это может произойти, когда детали реализации меняются из-за рефакторинга кода приложения. С другой стороны, ложные положительные результаты возникают, когда тест пройден, даже если тестируемый код некорректен.

Одним из решений этой проблемы является рассмотрение различных типов пользователей. Конечные пользователи и разработчики могут различаться в подходах, и они могут взаимодействовать с кодом по-разному. При планировании тестов важно учитывать, что пользователи будут видеть или с чем будут взаимодействовать, и делать тесты зависимыми от этих вещей, а не от деталей реализации.

Например, выбор селекторов, которые менее подвержены изменениям, может сделать тесты более надежными: data-attributes вместо селекторов CSS. Для получения более подробной информации обратитесь к статье Кента С. Доддса на эту тему или следите за обновлениями — статья на эту тему появится позже.

Насмешка: Не теряй контроль

Mocking — это широкое понятие, используемое в модульном тестировании, а иногда и в интеграционном тестировании. Оно подразумевает создание поддельных данных или компонентов для имитации зависимостей, которые полностью контролируют приложение. Это позволяет проводить изолированное тестирование.

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

В то же время, фиктивные тесты могут повлиять на точность теста, поскольку это фиктивные тесты, а не реальный пользовательский опыт. Поэтому вам нужно быть внимательными при использовании фиктивных тестов и заглушек.

Стоит ли проводить имитационные тесты в сквозных тестах?

В целом, нет. Однако иногда насмешки могут спасти жизнь, поэтому не будем исключать их полностью.

Представьте себе такой сценарий: вы пишете тест для функции, включающей сторонний платежный сервис. Вы находитесь в среде песочницы, которую они предоставили, то есть никаких реальных транзакций не происходит. К сожалению, песочница работает со сбоями, из-за чего ваши тесты не проходят. Исправление должно быть выполнено платежным сервисом. Все, что вы можете сделать, это подождать, пока проблема будет решена поставщиком.

В этом случае может быть более полезным уменьшить зависимость от служб, которые вы не можете контролировать. По-прежнему рекомендуется осторожно использовать заглушки в интеграционных или сквозных тестах, поскольку это снижает уровень достоверности ваших тестов.

Особенности теста: что можно и чего нельзя делать

Итак, в целом, что содержит тест? И есть ли различия между типами тестирования? Давайте подробнее рассмотрим некоторые конкретные аспекты, соответствующие основным типам тестирования.

Что входит в хороший модульный тест?

Идеальный и эффективный модульный тест должен:

  • Сосредоточьтесь на конкретных аспектах.
  • Действуйте независимо.
  • Охватывайте сценарии малого масштаба.
  • Используйте описательные имена.
  • Если применимо, следуйте шаблону AAA.
  • Гарантия комплексного тестирования.
Делай ✅ Не надо ❌
Сохраняйте тесты как можно более короткими. Тестируйте одну вещь на каждый тестовый случай. Пишите тесты для больших модулей.
Всегда держите тесты изолированными и имитируйте то, что вам нужно, но находится за пределами вашего подразделения. Включите другие компоненты или услуги.
Сохраняйте независимость тестов. Опирайтесь на предыдущие тесты или делитесь данными тестов.
Охватывайте различные сценарии и пути . Ограничьтесь счастливым путем или максимум отрицательными тестами.
Используйте описательные названия тестов, чтобы вы сразу могли понять, о чем ваш тест. Тест только по имени функции, в результате чего он недостаточно описателен: testBuildFoo() или testGetId() .
Стремитесь к хорошему покрытию кода или более широкому диапазону тестовых случаев, особенно на этом этапе. Тестирование от каждого класса до уровня базы данных (ввода-вывода).

Что входит в хороший интеграционный тест?

Идеальный интеграционный тест также разделяет некоторые критерии с модульными тестами. Однако есть несколько дополнительных моментов, которые вам нужно учесть. Отличный интеграционный тест должен:

  • Моделировать взаимодействие между компонентами.
  • Охватывайте реальные сценарии и используйте макеты или заглушки.
  • Подумайте о производительности.
Делай ✅ Не надо ❌
Проверьте точки интеграции: убедитесь, что все блоки корректно работают вместе при интеграции друг с другом. Тестируйте каждый модуль по отдельности — именно для этого и предназначены модульные тесты.
Тестируйте реальные сценарии: используйте тестовые данные, полученные из реальных данных. Используйте повторяющиеся автоматически сгенерированные тестовые данные или другие данные, которые не отражают реальные варианты использования.
Используйте заглушки и макеты для внешних зависимостей, чтобы сохранить контроль над всем тестом. Создавать зависимости от сторонних служб, например, сетевые запросы к внешним службам.
Используйте процедуру очистки до и после каждого теста. Забудьте о необходимости использовать меры очистки внутри своих тестов, в противном случае это может привести к сбоям в тестах или ложным срабатываниям из-за отсутствия надлежащей изоляции тестов.

Что входит в хороший сквозной тест?

Комплексное сквозное тестирование должно:

  • Дублируйте взаимодействия с пользователем.
  • Охватывайте жизненно важные сценарии.
  • Охватывает несколько слоев.
  • Управление асинхронными операциями.
  • Проверьте результаты.
  • Учет производительности.
Делай ✅ Не надо ❌
Используйте API-управляемые сочетания клавиш. Узнать больше . Используйте взаимодействия с пользовательским интерфейсом на каждом этапе, включая хук beforeEach .
Используйте процедуру очистки перед каждым тестом. Уделяйте больше внимания изоляции теста, чем в модульных и интеграционных тестах, поскольку здесь выше риск побочных эффектов. Забывать убирать после каждого теста. Если не убирать оставшееся состояние, данные или побочные эффекты, они повлияют на другие тесты, выполняемые позже.
Рассматривайте сквозные тесты как системные тесты. Это означает, что вам нужно тестировать весь стек приложений. Тестируйте каждый модуль по отдельности — именно для этого и предназначены модульные тесты.
Используйте минимальное или отсутствующее мокирование внутри теста. Тщательно обдумайте, хотите ли вы мокировать внешние зависимости. В значительной степени полагайтесь на имитации.
Учитывайте производительность и рабочую нагрузку, например, не тестируйте слишком много больших сценариев в одном тесте. Охватывайте большие рабочие процессы без использования сочетаний клавиш.
,

Определите, что вам необходимо проверить, а что можно исключить.

В предыдущей статье были рассмотрены основы тестовых случаев и то, что они должны содержать. В этой статье более подробно рассматривается создание тестовых случаев с технической точки зрения, подробно описывается, что должно быть включено в каждый тест и чего следует избегать. По сути, вы узнаете ответ на извечные вопросы «Что тестировать» или «Что не тестировать».

Что тестировать или не тестировать.

Общие рекомендации и шаблоны

Стоит отметить, что определенные шаблоны и точки имеют решающее значение, независимо от того, проводите ли вы модульные, интеграционные или сквозные тесты. Эти принципы могут и должны применяться к обоим типам тестирования, поэтому они являются хорошей отправной точкой.

Будьте проще

Когда дело доходит до написания тестов, одна из самых важных вещей, которую нужно помнить, — это простота. Важно учитывать возможности мозга. Основной производственный код занимает значительное место, оставляя мало места для дополнительной сложности. Это особенно актуально для тестирования.

Если свободного пространства меньше, вы можете расслабиться в своих усилиях по тестированию. Вот почему крайне важно отдавать приоритет простоте в тестировании. Фактически, лучшие практики тестирования JavaScript Йони Голдберга подчеркивают важность Золотого правила — ваш тест должен ощущаться как помощник, а не как сложная математическая формула. Другими словами, вы должны быть в состоянии понять цель вашего теста с первого взгляда.

Не усложняйте тесты, они не должны быть такими.

Вы должны стремиться к простоте во всех типах тестов, независимо от их сложности. Фактически, чем сложнее тест, тем важнее его упростить. Один из способов добиться этого — использовать плоский дизайн теста, где тесты максимально просты и тестировать только то, что необходимо. Это означает, что каждый тест должен содержать только один тестовый случай, и тестовый случай должен быть сосредоточен на тестировании одной конкретной функциональности или функции.

Подумайте об этом с этой точки зрения: должно быть легко определить, что пошло не так, при чтении проваленного теста. Вот почему важно, чтобы тесты были простыми и понятными. Это позволит вам быстро выявлять и устранять проблемы, когда они возникают.

Проверьте, что того стоит

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

Не проверяйте все подряд.

Не проверяйте детали реализации

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

Ложные отрицательные результаты возникают, когда тест не пройден, даже если тестируемый код корректен. Это может произойти, когда детали реализации меняются из-за рефакторинга кода приложения. С другой стороны, ложные положительные результаты возникают, когда тест пройден, даже если тестируемый код некорректен.

Одним из решений этой проблемы является рассмотрение различных типов пользователей. Конечные пользователи и разработчики могут различаться в подходах, и они могут взаимодействовать с кодом по-разному. При планировании тестов важно учитывать, что пользователи будут видеть или с чем будут взаимодействовать, и делать тесты зависимыми от этих вещей, а не от деталей реализации.

Например, выбор селекторов, которые менее подвержены изменениям, может сделать тесты более надежными: data-attributes вместо селекторов CSS. Для получения более подробной информации обратитесь к статье Кента С. Доддса на эту тему или следите за обновлениями — статья на эту тему появится позже.

Насмешка: Не теряй контроль

Mocking — это широкое понятие, используемое в модульном тестировании, а иногда и в интеграционном тестировании. Оно подразумевает создание поддельных данных или компонентов для имитации зависимостей, которые полностью контролируют приложение. Это позволяет проводить изолированное тестирование.

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

В то же время, фиктивные тесты могут повлиять на точность теста, поскольку это фиктивные тесты, а не реальный пользовательский опыт. Поэтому вам нужно быть внимательными при использовании фиктивных тестов и заглушек.

Стоит ли проводить имитационные тесты в сквозных тестах?

В целом, нет. Однако иногда насмешки могут спасти жизнь, поэтому не будем исключать их полностью.

Представьте себе такой сценарий: вы пишете тест для функции, включающей сторонний платежный сервис. Вы находитесь в среде песочницы, которую они предоставили, то есть никаких реальных транзакций не происходит. К сожалению, песочница работает со сбоями, из-за чего ваши тесты не проходят. Исправление должно быть выполнено платежным сервисом. Все, что вы можете сделать, это подождать, пока проблема будет решена поставщиком.

В этом случае может быть более полезным уменьшить зависимость от служб, которые вы не можете контролировать. По-прежнему рекомендуется осторожно использовать заглушки в интеграционных или сквозных тестах, поскольку это снижает уровень достоверности ваших тестов.

Особенности теста: что можно и чего нельзя делать

Итак, в целом, что содержит тест? И есть ли различия между типами тестирования? Давайте подробнее рассмотрим некоторые конкретные аспекты, соответствующие основным типам тестирования.

Что входит в хороший модульный тест?

Идеальный и эффективный модульный тест должен:

  • Сосредоточьтесь на конкретных аспектах.
  • Действуйте независимо.
  • Охватывайте сценарии малого масштаба.
  • Используйте описательные имена.
  • Если применимо, следуйте шаблону AAA.
  • Гарантия комплексного тестирования.
Делай ✅ Не надо ❌
Сохраняйте тесты как можно более короткими. Тестируйте одну вещь на каждый тестовый случай. Пишите тесты для больших модулей.
Всегда держите тесты изолированными и имитируйте то, что вам нужно, но находится за пределами вашего подразделения. Включите другие компоненты или услуги.
Сохраняйте независимость тестов. Опирайтесь на предыдущие тесты или делитесь данными тестов.
Охватывайте различные сценарии и пути . Ограничьтесь счастливым путем или максимум отрицательными тестами.
Используйте описательные названия тестов, чтобы вы сразу могли понять, о чем ваш тест. Тест только по имени функции, в результате чего он недостаточно описателен: testBuildFoo() или testGetId() .
Стремитесь к хорошему покрытию кода или более широкому диапазону тестовых случаев, особенно на этом этапе. Тестирование от каждого класса до уровня базы данных (ввода-вывода).

Что входит в хороший интеграционный тест?

Идеальный интеграционный тест также разделяет некоторые критерии с модульными тестами. Однако есть несколько дополнительных моментов, которые вам нужно учесть. Отличный интеграционный тест должен:

  • Моделировать взаимодействие между компонентами.
  • Охватывайте реальные сценарии и используйте макеты или заглушки.
  • Подумайте о производительности.
Делай ✅ Не надо ❌
Проверьте точки интеграции: убедитесь, что все блоки корректно работают вместе при интеграции друг с другом. Тестируйте каждый модуль по отдельности — именно для этого и предназначены модульные тесты.
Тестируйте реальные сценарии: используйте тестовые данные, полученные из реальных данных. Используйте повторяющиеся автоматически сгенерированные тестовые данные или другие данные, которые не отражают реальные варианты использования.
Используйте заглушки и макеты для внешних зависимостей, чтобы сохранить контроль над всем тестом. Создавать зависимости от сторонних служб, например, сетевые запросы к внешним службам.
Используйте процедуру очистки до и после каждого теста. Забудьте о необходимости использовать меры очистки внутри своих тестов, в противном случае это может привести к сбоям в тестах или ложным срабатываниям из-за отсутствия надлежащей изоляции тестов.

Что входит в хороший сквозной тест?

Комплексное сквозное тестирование должно:

  • Дублируйте взаимодействия с пользователем.
  • Охватывайте жизненно важные сценарии.
  • Охватывает несколько слоев.
  • Управление асинхронными операциями.
  • Проверьте результаты.
  • Учет производительности.
Делай ✅ Не надо ❌
Используйте API-управляемые сочетания клавиш. Узнать больше . Используйте взаимодействия с пользовательским интерфейсом на каждом этапе, включая хук beforeEach .
Используйте процедуру очистки перед каждым тестом. Уделяйте больше внимания изоляции теста, чем в модульных и интеграционных тестах, поскольку здесь выше риск побочных эффектов. Забывать убирать после каждого теста. Если не убирать оставшееся состояние, данные или побочные эффекты, они повлияют на другие тесты, выполняемые позже.
Рассматривайте сквозные тесты как системные тесты. Это означает, что вам нужно тестировать весь стек приложений. Тестируйте каждый модуль по отдельности — именно для этого и предназначены модульные тесты.
Используйте минимальное или отсутствующее мокирование внутри теста. Тщательно обдумайте, хотите ли вы мокировать внешние зависимости. В значительной степени полагайтесь на имитации.
Учитывайте производительность и рабочую нагрузку, например, не тестируйте слишком много больших сценариев в одном тесте. Охватывайте большие рабочие процессы без использования сочетаний клавиш.