Это руководство было написано для Vue.js 3 и Vue Test Utils v2.
Версия для Vue.js 2 здесь.
# Установка vue-cli
vue-test-utils
– официальная библиотека для тестирования vue компонентов. Она работает как в браузере, так и в среде Node.js, позволяет работать в связке с любым тест-ранером. Мы будем запускать тесты через Node.js.
vue-cli
– самый простой способ начать работу. Он установит всё необходимое для проекта, сконфигурирует Jest – популярный фреймворк для тестирования. Установим cli, написав в консоли:
yarn global add @vue/cli
или через npm:
npm install -g @vue/cli
Создадим новый проект, написав vue create [project-name]
. Выберем "Manually select features" и для "Unit Testing" указываем Jest.
Как только установка закончится, переходим в проект через cd
и запускаем yarn test:unit
. Если всё сделано правильно, вы увидите:
PASS tests/unit/example.spec.js
HelloWorld.vue
✓ renders props.msg when passed (14ms)
Test Suites: 1 passed, 1 total
Tests: 1 passed, 1 total
Snapshots: 0 total
Time: 1.79s
Поздравляю, вы только что запустили свой первый тест!
# Пишем первый тест
Мы запускали тест, который установился вместе с проектом. Теперь давайте напишем собственный компонент и тест к нему. По традиции, когда работают с TDD, вы сначала пишите тесты, которые падают, а затем пишите код, который позволит тестам пройти проверку. Для начала, создадим наш компонент.
Нам больше не нужен src/components/HelloWorld.vue
и tests/unit/example.spec.js
поэтому удалим их.
# Создаём компонент Greeting
Создадим Greeting.vue
в src/components
. Внутри Greeting.vue
, добавим следующее:
<template>
<div>
{{ greeting }}
</div>
</template>
<script>
export default {
name: "Greeting",
data() {
return {
greeting: "Vue и TDD"
}
}
}
</script>
# Написание теста
Greeting
делает только одну вещь – выводит значение greeting
. Стратегия будет такая:
- отрисовываем компонент через
mount
- проверяем, что
component
содержит в себе значение "Vue и TDD"
Создадим Greeting.spec.js
внутри tests/unit
. Затем импортируем Greeting.vue
и mount
, добавим разметку для теста:
import { mount } from '@vue/test-utils'
import Greeting from '@/components/Greeting.vue'
describe('Greeting.vue', () => {
it('отрисовывает приветствие', () => {
})
})
Существует несколько различных синтаксисов, используемых при TDD. Мы будем использовать describe
и it
– синтаксис, который используется в Jest. В describe
обычно пишут что именно тестируют, в нашем случае Greeting.vue
. В it
содержится функция, которая проверяет конкретную часть кода. Для каждой функции компонента, мы добавляем свой блок с it
.
Теперь нам нужно отрисовать компонент с помощью mount
. Обычно компонент присваивают какой-либо переменной, которую называют wrapper
. Выведем содержимое компонента, убедимся, что всё запускается правильно.
const wrapper = mount(Greeting)
console.log(wrapper.html())
# Запускаем тест
Запустим тест, написав в консоли yarn test:unit
. Все файлы из папки tests
c расширением .spec.js
автоматически выполнятся. Если всё сделано правильно, вы увидите:
PASS tests/unit/Greeting.spec.js
Greeting.vue
✓ отрисовывает приветствие (27ms)
console.log tests/unit/Greeting.spec.js:7
<div>
Vue и TDD
</div>
Как мы видим, разметка компонента правильная, тест прошёл проверку. Правда, такой тест никогда не упадёт, поэтому он не очень полезный. Даже если мы удалим greeting
из Greeting.vue
– тест всё равно пройдёт. Давайте исправим это.
# Добавление проверки
Нам нужно сделать проверку, чтобы быть уверенными в том, что компонент ведёт себя так, как нужно. Мы можем сделать это через Jest's expect
API. Оно выглядит так: expect(текущий результат).to [матчер] (ожидаемый результат)
Матчер – это функция, которая сравнивает значения. Например:
expect(1).toBe(1)
Полный список матчеров можно посмотреть в документации Jest. Во vue-test-utils
нет матчеров, но нам достаточно тех, что предоставляет Jest. Нам нужно сравнить текст в Greeting
. Мы можем написать:
expect(wrapper.html().includes("Vue и TDD")).toBe(true)
но vue-test-utils
предоставляет ещё лучший способ – wrapper.text
. Давайте допишем наш тест:
import { mount } from '@vue/test-utils'
import Greeting from '@/components/Greeting.vue'
describe('Greeting.vue', () => {
it('отрисовывает приветствие', () => {
const wrapper = mount(Greeting)
expect(wrapper.text()).toMatch("Vue и TDD")
})
})
Нам больше не нужен console.log
, удалим его. Запустим тесты yarn test:unit
и если всё сделано правильно, у вас должно получиться:
PASS tests/unit/Greeting.spec.js
Greeting.vue
✓ отрисовывает приветствие (15ms)
Test Suites: 1 passed, 1 total
Tests: 1 passed, 1 total
Snapshots: 0 total
Time: 1.477s, estimated 2s
Выглядит отлично, но вы должны всегда видеть, что тест сначала не проходит проверку, а затем проходит, чтобы убедиться в правильности теста. В традиционном TDD, вы сначала пишите неработающие тесты, затем используете полученные ошибки при написании кода. Давайте убедимся, что всё работает правильно. Обновим Greeting.vue
:
<template>
<div>
{{ greeting }}
</div>
</template>
<script>
export default {
name: "Greeting",
data() {
return {
greeting: "Vue без TDD"
}
}
}
</script>
Запустим тесты через yarn test:unit
:
FAIL tests/unit/Greeting.spec.js
Greeting.vue
✕ отрисовывает приветствие (24ms)
● Greeting.vue › отрисовывает приветствие
expect(received).toMatch(expected)
Expected value to match:
"Vue и TDD"
Received:
"Vue без TDD"
6 | const wrapper = mount(Greeting)
7 |
> 8 | expect(wrapper.text()).toMatch("Vue и TDD")
| ^
9 | })
10 | })
11 |
at Object.<anonymous> (tests/unit/Greeting.spec.js:8:28)
Jest даёт нам хороший фидбек. Мы видим ожидаемый и полученный результат, а также строку, в которой произошла ошибка. Тест не прошёл проверку, как и ожидалось. Вернём прежнее значение в Greeting.vue
и убедимся, что тест снова проходит проверку.
В следующих блоках мы рассмотрим два метода отрисовки, которые предоставляет vue-test-utils
– это mount
и shallowMount
.