Книга рецептовbeta
- Введение
- Добавление свойств экземпляра
- Валидация форм
- Редактируемая система SVG-иконок
- Создание блога, управляемого CMS
- Модульное тестирование Vue-компонентов
- Создание пользовательской директивы прокрутки
- Отладка в VS Code
- Используем axios для доступа к API
- Устранение утечек памяти
- Хранение данных на стороне клиента
- Публикация Vue-компонентов в npm
- Интегрируем Docker в приложение Vue.js
- Практическое использование слотов с ограниченной областью видимости с GoogleMaps
Эта документация для версий v2.x и ранее. Для v3.x, документация на русском здесь.
Модульное тестирование Vue-компонентов
Простой пример
Модульное тестирование — фундаментальная часть разработки программного обеспечения. В модульных тестах выполняются небольшие фрагменты (единицы) кода в изоляции для упрощения добавления новых функциональных возможностей и отслеживания ошибок. Однофайловые компоненты Vue позволяют просто писать модульные тесты для компонентов в изоляции. Это поможет вам разрабатывать новую функциональность с уверенностью, что вы не ломаете работу существующей, и помогает другим разработчикам понять, как работает компонент.
Этот простой пример проверяет, отрисовывается ли какой-либо текст:
|
|
Вышеприведённый фрагмент кода показывает, как проверить, отрисовывается ли сообщение в зависимости от длины имени пользователя. Он демонстрирует общую идею модульного тестирования Vue-компонентов: отрисовка компонента и проверка, что разметка соответствует состоянию компонента.
Зачем тестировать?
У модульных тестов компонентов есть множество преимуществ:
- Предоставляет документацию, как должен работать компонент
- Экономит время на ручное тестирование
- Уменьшает баги при реализации новой функциональности
- Улучшает дизайн кода
- Способствует рефакторингу кода
Автоматическое тестирование позволяет большим командам разработчиков поддерживать сложную кодовую базу.
Начало работы
Vue Test Utils — официальная библиотека для модульного тестирования Vue-компонентов. Шаблон webpack
vue-cli идёт в комплекте с Karma или Jest, как с хорошо поддерживаемыми программами запуска тестов, и есть некоторые руководства в документации Vue Test Utils.
Пример из реального мира
Модульные тесты должны быть:
- Быстрыми для выполнения
- Простыми для понимания
- Тестировать только единственный участок функциональности
Давайте продолжим работу с предыдущим примером, представив идею фабричной функцию, чтобы сделать наш тест более компактным и читаемым. Компонент должен:
- показать приветствие ‘Добро пожаловать в книгу рецептов Vue.js’.
- попросить пользователя ввести своё имя пользователя
- показать ошибку, если введённое имя пользователя меньше семи символов
Давайте сначала рассмотрим код компонента:
|
Список из того, что нам нужно проверить:
- отобразилось ли свойство
message
? - если
error
равноtrue
, в разметке должен быть<div class="error">
- если
error
равноfalse
, в разметке не должно быть<div class="error">
И наша первая попытка теста:
|
Есть несколько проблем с вышеприведённым кодом:
- в одном тесте проверяются сразу много чего
- трудно определить различные состояния компонента, и что должно отрисовываться
В примере ниже тестирование улучшается с помощью следующих правил:
- один блок
it
содержит только один вызовexpect
- наличие краткого и чёткого описания для каждого теста
- предоставление только минимальных данных, требуемых для выполнения теста
- рефакторинг дублирования логики (создание
wrapper
и установка переменнойusername
) в фабричную функцию
Обновлённый тест:import { shallowMount } from '@vue/test-utils'
import Foo from './Foo.vue'
const factory = (values = {}) => {
return shallowMount(Foo, {
data () {
return {
...values
}
}
})
}
describe('Foo', () => {
it('отрисовывает приветственное сообщение', () => {
const wrapper = factory()
expect(wrapper.find('.message').text()).toEqual('Добро пожаловать в книгу рецептов Vue.js')
})
it('отрисовывает ошибку, когда имя пользователя меньше 7 символов', () => {
const wrapper = factory({ username: '' })
expect(wrapper.find('.error').exists()).toBeTruthy()
})
it('отрисовывает ошибку, когда имя пользователя состоит только из пробелов', () => {
const wrapper = factory({ username: ' '.repeat(7) })
expect(wrapper.find('.error').exists()).toBeTruthy()
})
it('не отрисовывает ошибку, когда имя пользователя равно 7 символам или более', () => {
const wrapper = factory({ username: 'Александр' })
expect(wrapper.find('.error').exists()).toBeFalsy()
})
})
Следует отметить:
В верхней части мы объявляем фабричную функцию, когда объединяет объект values
в свойство data
и возвращает новый экземпляр wrapper
. Таким образом, нам не нужно дублировать const wrapper = shallowMount(Foo)
в каждом тесте. Ещё одним большим преимуществом использования такого подхода — случаи, когда в более комплексных компонентах, с методом или вычисляемым свойством, вы захотите имитировать (mock) или создавать заглушку (stub) в каждом тесте, тогда вам нужно будет объявить его только один раз.
Дополнительный контекст
Вышеприведённый тест довольно прост, но на практике у Vue-компонентов часто другое поведение, которые вы хотите проверить, например:
- вызовы к API
- совершение или отправка мутаций или действий с хранилищем
Vuex
- тестирования взаимодействия
Более подробные примеры, показывающие такие тесты в действии, вы можете найти в руководствах.
Vue Test Utils и огромная экосистема JavaScript обеспечивают множество инструментов чтобы обеспечить почти 100% покрытия тестами. Однако модульные тесты являются лишь частью пирамиды тестирования. Есть и другие типы тестов, включая тесты e2e (end-to-end) и тесты снимками (snapshot). Модульные тесты — это самые маленькие и самые простые тесты — они проверяют утверждения на маленьких единицах работы, изолируя каждую часть единственного компонента.
Тесты снимками сохраняют разметку вашего Vue-компонента и сравнивают с новой, создаваемой при каждом выполнении теста. Если что-то изменяется, разработчик будет в курсе и сможет решить, было ли решение намеренным (компонент был обновлён) или случайным (компонент работает некорректно).
Тесты end-to-end гарантирует, что несколько компонентов хорошо взаимодействуют друг с другом. Они находятся на более высоком уровне. Примерами таких тестов может быть тестирование регистрации, входа и изменения данных у пользователя. Они работают медленнее, чем модульные тесты или тестирование снимками.
Модульные тесты наиболее полезны во время разработки, либо чтобы помочь разработчику подумать спроектировать компонент, либо отрефакторить существующий компонент. Они запускаются каждый раз при изменении кода.
Тесты высокого уровня, такие как end-to-end тесты, работают намного медленнее. Обычно их запускают перед публикацией сайта для гарантии, что каждая часть системы работает корректно.
Более подробную информацию о тестировании Vue-компонентов вы можете найти в книге Testing Vue.js Applications от члена команды Эдда Йербурга.
Когда не следует тестировать
Модульное тестирование — важная часть любого серьёзного приложения. Сначала, когда видение развития приложения остаётся неясным, модульное тестирование может замедлить разработку, но после стабилизации направления развития и взаимодействия с настоящими пользователями, модульные тесты (и другие типы автоматических тестов) абсолютно необходимы для обеспечения удобства в поддержке и масштабируемости кодовой базы.