Виктор Савкин - соучредитель nrwl.io, предоставляющий Angular консалтинг корпоративным командам. Ранее он входил в основную команду Angular в Google и создавал модули внедрения зависимостей, обнаружения изменений, форм и маршрутизатора.

Одна из целей разработки Angular - упростить тестирование. Вот почему фреймворк полагается на внедрение зависимостей, отделяет пользовательский код от кода фреймворка и поставляется с набором инструментов для написания и выполнения тестов. В этой статье я рассмотрю четыре способа тестирования компонентов Angular: изолированные тесты, неглубокие тесты, интеграционные тесты и тесты транспортира.

Прочитать серию

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

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

Пример приложения

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

Вы можете найти исходный код приложения здесь.

Изолированные тесты

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

Filters.component.html:

В этом примере стоит отметить несколько моментов:

  • Мы используем реактивные формы в шаблоне этого компонента. Это требует, чтобы мы вручную создали объект формы в классе компонента, что имеет приятные последствия: мы можем протестировать обработку ввода без отрисовки шаблона.
  • Мы прослушиваем все изменения формы, устраняем их с помощью оператора RxJS debounceTime, а затем генерируем событие изменения.
  • Наконец, мы внедряем функцию для создания объекта фильтров вне формы.

А теперь давайте посмотрим на тест.

Как видите, изолированное тестирование компонентов Angular ничем не отличается от тестирования любого другого объекта JavaScript. Мы не используем никаких утилит, специфичных для пользовательского интерфейса Angular. Однако мы используем fakeAsync. Это утилита, предоставляемая zone.js, и с ее помощью мы можем контролировать время, что удобно для тестирования устранения неполадок. Кроме того, в этом тесте не используется шаблон этого компонента. Шаблон также может быть пустым - тест все равно пройдет.

Неглубокое тестирование

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

Давайте посмотрим на этот подход в действии.

Этот компонент просто отображает коллекцию TalkCmp.

Теперь давайте посмотрим на его тест.

Сначала посмотрим, как мы настроили наш тестовый модуль. Мы только объявили TalksCmp, больше ничего. Это означает, что все элементы в шаблоне будут обрабатываться как простые узлы DOM, и будут применяться только общие директивы (например, ngIf и ngFor). Это именно то, что мы хотим. Во-вторых, передача NO_ERRORS_SCHEMA сообщает компилятору не допускать ошибок для неизвестных элементов и атрибутов, что нам и нужно для неглубоких тестов. В результате будет создан список элементов DOM talk-cmp, которые мы проверили в ходе теста. Не было создано ни одного экземпляра TalkCmp.

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

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

Обратите внимание, что здесь мы импортируем AppModule, что означает, что Angular создаст все зарегистрированные поставщики и скомпилирует все зарегистрированные компоненты. Сам тест не требует пояснений.

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

Транспортир Тесты

Наконец, мы всегда можем написать тест транспортира, проверяющий все приложение.

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

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

Подведем итоги

В этой статье мы рассмотрели четыре способа тестирования компонентов Angular: изолированные тесты, поверхностные тесты, интеграционные тесты и тесты транспортира. У каждого из них свое время и место: изолированные тесты - отличный способ протестировать ваши компоненты и проверить сложную логику. Мелкие тесты - это изолированные тесты на стероидах, и их следует использовать при написании содержательного теста, требующего визуализации шаблона компонента. Наконец, тесты интеграции и транспортира подтверждают, что группа компонентов и сервисов (то есть приложение) работают вместе.

Основная книга Angular

Эта статья основана на книге Essential Angular, которую вы можете найти здесь https://leanpub.com/essential_angular. Если вам понравилась статья, загляните в книгу!

Виктор Савкин - соучредитель Nrwl. Мы помогаем компаниям развиваться, как Google, с 2016 года. Мы предоставляем консультации, инжиниринг и инструменты.

Если вам это понравилось, нажмите 👏 ниже, чтобы другие люди увидели это здесь, на Medium. Подпишитесь на @victorsavkin, чтобы узнать больше о монорепозиториях, Nx, Angular и React.