Анализ отчетов

Для начала работы с Vue Test Utils требуется установка библиотеки через npm или yarn:

npm install @vue/test-utils --save-dev
# или
yarn add @vue/test-utils --dev

Vue Test Utils (VTU) позволяет создавать шаблоны компонентов и взаимодействовать с ними в изолированной среде. Основная точка входа — функция mount, которая рендерит компонент в тестовой среде.

import { mount } from '@vue/test-utils';
import MyComponent from '@/components/MyComponent.vue';

const wrapper = mount(MyComponent, {
  props: { title: 'Тестовый заголовок' }
});

wrapper — это объект, предоставляющий методы для поиска элементов, проверки их состояния и симуляции пользовательских действий.


Структура тестов

Тесты с использованием VTU обычно строятся вокруг трёх ключевых элементов:

  1. Создание обёртки (wrapper) — рендеринг компонента.
  2. Взаимодействие с компонентом — изменение состояния, вызов методов, симуляция событий.
  3. Проверка результатов — утверждения с использованием Jest, Vitest или другого тестового раннера.

Пример простого теста:

test('отображает переданный заголовок', () => {
  const wrapper = mount(MyComponent, { props: { title: 'Привет' } });
  expect(wrapper.text()).toContain('Привет');
});

Работа с DOM

VTU предоставляет методы для поиска элементов:

  • wrapper.find(selector) — возвращает первый элемент, соответствующий селектору.
  • wrapper.findAll(selector) — возвращает массив всех элементов по селектору.

Для проверки содержимого и атрибутов используется:

const button = wrapper.find('button');
expect(button.text()).toBe('Нажми меня');
expect(button.attributes('disabled')).toBeUndefined();

Методы classes(), attributes(), element и html() позволяют получать состояние элемента и проверять соответствие ожиданиям.


Симуляция пользовательских действий

Vue Test Utils позволяет симулировать события через метод trigger:

const button = wrapper.find('button');
await button.trigger('click');
expect(wrapper.emitted()).toHaveProperty('submit');

Можно передавать объект события для имитации реальных условий:

await button.trigger('keydown.enter', { key: 'Enter' });

Тестирование пропсов и реактивности

Пропсы можно передавать при создании wrapper или динамически изменять через setProps:

await wrapper.setProps({ title: 'Новый заголовок' });
expect(wrapper.text()).toContain('Новый заголовок');

Реактивные данные проверяются через изменение состояния компонента:

wrapper.vm.counter = 5;
await wrapper.vm.$nextTick();
expect(wrapper.text()).toContain('5');

nextTick необходим для обновления DOM после изменения реактивных данных.


Работа с событиями и эмиттерами

Компоненты часто взаимодействуют через $emit. Проверка событий выполняется через методы emitted и emittedByOrder:

await wrapper.find('button').trigger('click');
expect(wrapper.emitted('submit')).toHaveLength(1);
expect(wrapper.emitted('submit')[0]).toEqual([{ id: 1 }]);

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


Взаимодействие с дочерними компонентами

VTU позволяет тестировать компоненты в изоляции или вместе с дочерними:

  • Shallow mount: игнорирует рендеринг дочерних компонентов, заменяя их заглушками.
import { shallowMount } from '@vue/test-utils';

const wrapper = shallowMount(MyComponent);
  • Полный mount: рендерит все дочерние компоненты, позволяя тестировать интеграцию.
const wrapper = mount(MyComponent);

shallowMount ускоряет тесты и уменьшает зависимость от других компонентов.


Тестирование асинхронных операций

Компоненты часто выполняют асинхронные действия, например, запросы к API. VTU интегрируется с Jest или Vitest для работы с асинхронным кодом:

await wrapper.vm.loadData();
await wrapper.vm.$nextTick();
expect(wrapper.text()).toContain('Данные загружены');

Методы flushPromises или nextTick обеспечивают корректное завершение всех промисов перед проверкой результатов.


Измерение покрытия кода и отчёты

Для анализа покрытия тестами используется инструмент jest --coverage или аналогичные для Vitest. Отчёт содержит:

  • Statements — количество проверенных выражений.
  • Branches — проверка всех ветвлений (if, switch).
  • Functions — покрытие методов.
  • Lines — строки кода, которые выполнялись при тестировании.

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


Рекомендации по структуре тестов

  • Разделять тесты на группы по функциональности компонента с помощью describe.
  • Проверять отдельные сценарии в независимых test или it.
  • Использовать beforeEach для создания нового wrapper перед каждым тестом, чтобы избежать побочных эффектов.
  • Применять shallowMount для изоляции тестов и ускорения их выполнения.
describe('MyComponent', () => {
  let wrapper;

  beforeEach(() => {
    wrapper = shallowMount(MyComponent);
  });

  test('отображает текст по умолчанию', () => {
    expect(wrapper.text()).toContain('Заголовок');
  });

  test('реагирует на изменение пропса', async () => {
    await wrapper.setProps({ title: 'Новый заголовок' });
    expect(wrapper.text()).toContain('Новый заголовок');
  });
});

Интеграция с Vuex и Vue Router

VTU позволяет подключать Vuex и Vue Router для тестирования компонентов в контексте приложения:

import { createStore } from 'vuex';
import { createRouter, createWebHistory } from 'vue-router';

const store = createStore({ state: { count: 0 } });
const router = createRouter({ history: createWebHistory(), routes: [] });

const wrapper = mount(MyComponent, {
  global: {
    plugins: [store, router]
  }
});

global.plugins и global.mocks позволяют настраивать глобальные зависимости без необходимости создавать полноценное приложение.