Тестирование 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+ лет, десятки проектов с высокой сложностью. Гарантируем качество и прозрачность процесса. Свяжитесь с нами, чтобы обсудить детали.







