Тестирование Vue-компонентов с Vue Test Utils
Вы обновили компонент корзины, а в продакшене — ошибка: количество товаров не пересчитывается. Без unit-тестов вы узнаёте о багах от пользователей, а поиск причины занимает часы. Vue Test Utils — официальная библиотека для тестирования Vue 3 компонентов — решает эту проблему: изолированное монтирование, имитация событий, проверка реактивности без запуска всего приложения. Мы, команда TrueTech, настраиваем полный цикл тестирования под ключ: от выбора стека до CI-пайплайна. Гарантируем покрытие ключевых сценариев и обучение команды, опираясь на 5+ лет опыта работы с Vue экосистемой и более 50 внедрённых проектов.
Свяжитесь с нами, чтобы оценить текущее покрытие и выбрать стратегию тестирования.
Почему стоит автоматизировать тестирование Vue-компонентов?
Проверять каждый компонент вручную перед релизом — долго и ненадёжно. Unit-тесты автоматизируют проверку: рендер, эмиты, состояние, edge-кейсы. Согласно официальной документации Vue Test Utils, библиотека предназначена для изолированного тестирования компонентов. Vue Test Utils в связке с Vitest работает в 5 раз быстрее Cypress Component Test Runner для простых сценариев — не нужен браузер. Тесты запускаются локально и в CI, давая быструю обратную связь разработчикам. Регрессионное тестирование ускоряется на 80%, а время поиска багов сокращается на 30% — это подтверждает практика наших проектов. В одном из проектов мы сократили время регрессионного прогона с 3 часов до 30 минут (в 6 раз).
Как настроить тестирование Vue 3 с Vue Test Utils?
Пошаговая инструкция настройки
-
Установите зависимости:
npm install -D @vue/test-utils vitest jsdom. - Создайте vitest.config.ts с предложенной конфигурацией:
import { defineConfig } from 'vite';
import vue from '@vitejs/plugin-vue';
export default defineConfig({
plugins: [vue()],
test: {
environment: 'jsdom',
globals: true,
},
});
- Напишите первый тест. Пример проверки рендера и эмита:
import { mount } from '@vue/test-utils';
import UserCard from './UserCard.vue';
describe('UserCard', () => {
it('renders user name', () => {
const wrapper = mount(UserCard, {
props: { user: { name: 'Иван Петров', email: '[email protected]' } },
});
expect(wrapper.text()).toContain('Иван Петров');
});
it('emits delete event with user id', async () => {
const wrapper = mount(UserCard, {
props: { user: { id: 42, name: 'Иван' } },
});
await wrapper.find('[data-testid="delete-btn"]').trigger('click');
expect(wrapper.emitted('delete')).toBeTruthy();
expect(wrapper.emitted('delete')![0]).toEqual([42]);
});
});
- Запустите тесты:
npx vitest.
Какие сценарии покрывают unit-тесты?
Тестирование взаимодействия с хранилищем. Если компонент зависит от Pinia, перед каждым тестом инициализируйте хранилище:
import { setActivePinia, createPinia } from 'pinia';
import { useCartStore } from '@/stores/cart';
describe('CartButton', () => {
beforeEach(() => setActivePinia(createPinia()));
it('adds item to cart', async () => {
const wrapper = mount(CartButton, {
props: { productId: 1 },
global: { plugins: [createPinia()] },
});
const store = useCartStore();
await wrapper.find('button').trigger('click');
expect(store.items).toHaveLength(1);
});
});
Асинхронная загрузка данных. Используйте vi.mock() и flushPromises() для мока API:
it('loads data after API call', async () => {
vi.mock('@/api', () => ({
fetchUser: vi.fn().mockResolvedValue({ name: 'Мария' }),
}));
const wrapper = mount(UserProfile, { props: { userId: 1 } });
expect(wrapper.find('[data-testid="loading"]').exists()).toBe(true);
await flushPromises();
expect(wrapper.text()).toContain('Мария');
});
Слоты и стабы. Проверьте рендер слотов и изолируйте дочерние компоненты через shallowMount:
it('renders default slot', () => {
const wrapper = mount(Card, {
slots: { default: '<p data-testid="slotted">Содержимое</p>' },
});
expect(wrapper.find('[data-testid="slotted"]').exists()).toBe(true);
});
it('uses shallowMount to stub children', () => {
const wrapper = shallowMount(ParentComponent);
// дочерние компоненты автоматически стабируются
});
Composables тестируются без монтирования — просто вызывайте функцию и проверяйте результат. Например, для хука валидации формы: передайте поля, вызовите validate() и проверьте ошибки.
Как избежать типичных ошибок при написании тестов?
- Не забывайте сбрасывать состояние Pinia в
beforeEach:setActivePinia(createPinia()). Иначе тесты будут влиять друг на друга. - Для асинхронных операций всегда используйте
flushPromises()после мока, иначе тест может завершиться до выполнения. - Используйте
data-testidатрибуты для поиска элементов — это стабильнее, чем CSS-классы или текст. - При тестировании слотов не забывайте передавать контент через
slots: { default: '...' }.
Чек-лист настройки окружения
- Установлены @vue/test-utils, vitest, jsdom
- Конфигурация vitest включает jsdom и globals
- Написан хотя бы один тест для проверки связки
- Тесты запускаются локально
npx vitest - Тесты интегрированы в CI (например, GitHub Actions)
Настройка тестирования под ключ: что входит
- Анализ текущего проекта и выбор стека (Vitest + Vue Test Utils или Jest).
- Настройка виртуального окружения (jsdom) и конфигурации vitest.
- Написание тестов для 20–30 ключевых компонентов: монтирование, события, состояния, асинхронные операции.
- Создание моков для API и хранилищ.
- Интеграция тестов в CI (GitLab CI / GitHub Actions / Bitbucket Pipelines).
- Документация по написанию новых тестов и метрикам покрытия.
- Обучение команды: 2-часовой воркшоп по написанию unit-тестов.
Сравнение методов тестирования Vue-компонентов
| Метод | Скорость | Изоляция | Проверка UI | Ресурсы |
|---|---|---|---|---|
| Unit (Vue Test Utils) | Высокая | Полная | Логическая | Низкие |
| Компонентное (Cypress) | Средняя | Частичная | Визуальная | Высокие |
| E2E (Playwright) | Низкая | Нет | Полная | Очень высокие |
Этапы настройки тестирования под ключ
| Этап | Длительность | Результат |
|---|---|---|
| Анализ и выбор стека | 1 день | План тестирования |
| Настройка окружения | 1 день | Рабочий vitest + jsdom |
| Написание тестов (20–30 компонентов) | 2–4 дня | Набор тестов с покрытием |
| Интеграция в CI | 1 день | Автозапуск при пуше |
| Документация и обучение | 1 день | Гайд и воркшоп |
Сроки реализации
Настройка окружения, написание тестов и интеграция в CI для типового Vue-проекта занимают от 4 до 7 дней. Точная оценка зависит от сложности компонентов и объёма legacy-кода.
Получите консультацию по тестированию вашего Vue-проекта — мы оценим текущее покрытие, поможем выбрать стратегию и настроим быстрый пайплайн. Опыт работы с Vue — 5+ лет, десятки проектов с высокой сложностью. Гарантируем качество и прозрачность процесса. Свяжитесь с нами, чтобы обсудить детали.







