ТЕСТИРОВАНИЕ ЯВАСКРИПТА

5 практик тестирования, которые вы должны иметь в своем пайплайне CI/CD

Никто не хочет ошибок в своих приложениях, это может привести к тому, что ваша компания потеряет миллионы долларов. Добавление этих 5 методов тестирования может предотвратить это с вами.

Позвольте мне рассказать вам историю…

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

Для меня это была совершенно новая концепция, я перешел из своей предыдущей компании, в которой был один или два выделенных QA в команде Scrum Development, к ZERO.

Я привык к тому, что коллега по команде просматривал мою ветку и добавлял автоматические тесты, тесты API или вручную тестировал ее для различных пограничных случаев и бизнес-потоков.

Что я буду делать без этого человека? Во время онбординга мы получили четкие инструкции, что мы должны следовать пирамиде тестирования:

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

И для моей первой задачи в команде я должен был что-то изменить в диалоге регистрации (довольно важная часть приложения)

Закончив с поставленной задачей, я провел небольшой рефакторинг, чтобы сделать код чище, и следовал пирамиде тестирования.

  • Я написал модульные тесты
  • Я написал интеграционные тесты
  • Я написал тест e2e

После этого я, конечно же, вручную протестировал фичу с несколькими пограничными случаями.

И конечный результат? Я сломал CSS почти во ВСЕХ диалоговых окнах приложения. И, конечно же, как назло, диалог, над которым я работал, не имел этой проблемы — он был великолепен.

Так что мы довольно рано поняли, что пирамида тестирования не работает.

Мы решили интегрировать больше проверок в наш конвейер CI/CD, чтобы убедиться, что новые столяры, такие как я, не будут так легко прерывать производство.

Но это не помешает разработчикам снизить SEO-рейтинг приложения за счет увеличения Core Web Vitals. Для этого нам необходимо провести тесты производительности.

Тесты производительности

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

Google идет дальше и повышает рейтинг SEO для веб-сайтов с более высокой производительностью. И он оценивает производительность на основе этих трех показателей.

  • FID (задержка первого входа)
  • LCP (наибольшая содержательная краска)
  • CLS (кумулятивный сдвиг макета)

Я не буду вдаваться в подробности каждой из этих метрик, но вы можете прочитать о них все в официальной документации от Google.

Мы заботимся о том, чтобы не ухудшить эти показатели при выпуске функции.

Для этого мы используем рекомендуемый инструмент Lighthouse CI (он поддерживается основными членами Google).

После того, как вы интегрировали библиотеку CI в свой конвейер, написание тестов производительности становится довольно простым делом.

В основном вас интересует только одна команда: cy.lighthouse(), которая запускает проверки производительности с помощью библиотеки cypress.

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

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

Мутационные тесты

И если говорить о тестах, которые нам приходится писать много… Модульные тесты существуют уже некоторое время.

Они находятся в нижней части пирамиды старой школы. Считаются наиболее важными, потому что они быстро работают и дешевы в написании. (Что может больше не иметь место в сегодняшней инфраструктуре Cloud Run)

Но как убедиться, что самая важная часть нашей тестовой инфраструктуры работает так, как ожидается?

Что, если некоторые из наших тестов дадут ложноположительный результат? Они отображаются в нашем терминале и CI зеленым цветом, но либо пропускаются, либо еще хуже: они написаны плохо и не проверяют результат тестируемой функции.

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

Давайте подумаем о простой функции sum.

Библиотека тестирования мутаций пройдёт эту функцию, проанализирует AST и найдёт все места, где она может изменить вашу функцию.

Например, он находит оператор + и может заменить его на другие операторы, такие как минус, умножение и т. д.

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

Вы можете проверить мутацию позже, отладить и улучшить свой код.

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

Визуальные тесты

Помните мою историю с начала статьи? Что ж, этого определенно не произошло бы, если бы у нас были визуальные тесты.

Как видно из названия, эти тесты позволяют убедиться, что визуально с вашими страницами все в порядке.

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

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

Они дают вам наибольшую уверенность, когда речь идет о CSS-части приложения.

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

Если вам приходилось нажимать кнопку или прокручивать страницу до конца, введение интерактивности также увеличивает ненадежность.

Тесты функций

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

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

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

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

Вы можете смонтировать свой компонент с разными реквизитами или вообще без реквизитов и протестировать поведение по умолчанию.

А затем взаимодействуйте с вашим компонентом сколько угодно, при этом видя результат в браузере.

Это также хороший способ разработки вашего компонента, если вам нравится писать TDD.

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

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

Будьте осторожны с E2E-тестами, хотя обычно они приносят с собой много проблем:

  • они медленные
  • Они полагаются на серверные службы для динамического отображения контента.
  • API может иметь более значительные задержки, чем период ожидания библиотеки E2E.
  • Вы наверняка несколько раз тестируете один и тот же участок пути пользователя.

У нас были все эти проблемы и многое другое, и мы применили некоторые методы, чтобы хотя бы уменьшить количество ненадёжности:

  • Мы запускаем наши E2E-тесты параллельно, вот хорошая статья о том, как этого добиться.
  • Мы реализовали функцию пропуска в наших тестах, имитируя файлы cookie или параметры URL. Пример: ?SKIP_LOGIN_FUNCTIONALITY=true, который имитирует вошедшего в систему пользователя (только при тестировании среды).
  • Мы смоделировали весь наш API, создав собственный фиктивный сервер, который записывает ответ в реальном времени. Вы можете прочитать больше об этом здесь."

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

Контрактные испытания

Мы обнаружили, что наиболее распространенной причиной всех наших сбоев было то, что ответ API отличался от ожидаемого внешним приложением.

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

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

Вы также указываете в своем контракте, что услуги, которые вы используете, в случае, если у вас есть несколько API или вы являетесь серверной службой, потребляющей несколько микросервисов.

Контракт затем сохраняется в библиотеке тестирования, которую вы используете, мы выбрали PACT, и для каждого внутреннего PR он запускает этот вывод провайдера для этого контракта. Если он не соблюдает контракт, PR блокируется.

Если вам понравилась эта статья, не забудьте подписаться на меня в среде или в Твиттере, чтобы узнать больше о том, что я хочу сказать. В основном о React Native, Frontend Engineering или Productivity.

Вот пара статей, которые я также написал: