Эта статья — перевод оригинальной статьи Ignacio Falk "Testing with Vitest"
Также я веду телеграм канал “Frontend по-флотски”, где рассказываю про интересные вещи из мира разработки интерфейсов.
Вступление
Vitest — это новая среда тестирования на базе Vite. Он все еще находится в разработке, и некоторые функции могут быть еще не готовы, но это хорошая альтернатива, которую можно попробовать и изучить.
Настройка
Давайте создадим новый проект Vite!
Примечание. Для работы Vitest требуется Vite >= v2.7.10 и Node >= v14.
npm init vite@latest
✔ Project name: · try-vitest
✔ Select a framework: · svelte
✔ Select a variant: · svelte-ts
cd try-vitest
npm install //use the package manager you prefer
npm run dev
Теперь, когда наш проект создан, нам нужно установить все зависимости, необходимые для работы Vitest.
npm i -D vitest jsdom
Я добавил jsdom, чтобы иметь возможность мокать DOM API. По умолчанию Vitest будет использовать конфигурацию из vite.config.ts. Я добавлю в неё один плагин для svelte. Отключение hot module replacement при выполнении тестов.
Это должно выглядеть следующим образом:
import { defineConfig } from 'vite'
import { svelte } from '@sveltejs/vite-plugin-svelte'
export default defineConfig({
plugins: [
svelte({ hot: !process.env.VITEST }),
],
})
Я использую переменную env VITEST, чтобы разделить окружение тестов и разработки, но если ваша конфигурация слишком отличается, вы можете использовать другой файл конфигурации для тестов. Есть несколько вариантов сделать это.
Создайте файл конфигурации с именем vitest.config.ts: он будет иметь приоритет при запуске тестов.
Использование флага --config: используйте его как
npx vitest --config <path_to_file>
Написание тестов
Давайте напишем несколько тестов для компонента Counter, созданного по умолчанию в нашем проекте.
<script lang="ts">
let count: number = 0
const increment = () => {
count += 1
}
</script>
<button on:click={increment}>
Clicks: {count}
</button>
<style>
button {
font-family: inherit;
font-size: inherit;
padding: 1em 2em;
color: #ff3e00;
background-color: rgba(255, 62, 0, 0.1);
border-radius: 2em;
border: 2px solid rgba(255, 62, 0, 0);
outline: none;
width: 200px;
font-variant-numeric: tabular-nums;
cursor: pointer;
}
button:focus {
border: 2px solid #ff3e00;
}
button:active {
background-color: rgba(255, 62, 0, 0.2);
}
</style>
Чтобы написать наш первый набор тестов, давайте создадим файл с именем Counter.spec.ts рядом с нашим компонентом.
// @vitest-environment jsdom
import { tick } from 'svelte';
import { describe, expect, it } from 'vitest';
import Counter from './Counter.svelte';
describe('Counter component', function () {
it('creates an instance', function () {
const host = document.createElement('div');
document.body.appendChild(host);
const instance = new Counter({ target: host });
expect(instance).toBeTruthy();
});
it('renders', function () {
const host = document.createElement('div');
document.body.appendChild(host);
new Counter({ target: host });
expect(host.innerHTML).toContain('Clicks: 0');
});
it('updates count when clicking a button', async function () {
const host = document.createElement('div');
document.body.appendChild(host);
new Counter({ target: host });
expect(host.innerHTML).toContain('Clicks: 0');
const btn = host.getElementsByTagName('button')[0];
btn.click();
await tick();
expect(host.innerHTML).toContain('Clicks: 1');
});
});
Добавление строки комментария @vitest-environment jsdom
вверху файла позволит нам мокать DOM API для всех тестов в файле. Этого можно избежать в каждом файле с помощью файла конфигурации. Мы также можем удостовериться, что мы импортируем describe
, it
, expect
глобально. Делаем это тоже через конфигурационный файл. Также нам нужно сделать типы доступными, добавив типы vitest/globals
в ваш файл tsconfig.json (вы можете пропустить это, если не используете TypeScript).
import { defineConfig } from 'vite'
import { svelte } from '@sveltejs/vite-plugin-svelte'
export default defineConfig({
plugins: [svelte({ hot: !process.env.VITEST })],
test: {
globals: true,
environment: 'jsdom',
},
});
{
"extends": "@tsconfig/svelte/tsconfig.json",
"compilerOptions": {
"target": "esnext",
"useDefineForClassFields": true,
"module": "esnext",
"resolveJsonModule": true,
"baseUrl": ".",
"allowJs": true,
"checkJs": true,
/**
*Add the next line if using globals
*/
"types": ["vitest/globals"]
},
"include": ["src/**/*.d.ts", "src/**/*.ts", "src/**/*.js", "src/**/*.svelte"]
}
Теперь нашим тестовым файлам не нужно импортировать глобальные переменные, и мы можем удалить настройку среды jsdom.
import { tick } from 'svelte';
import Counter from './Counter.svelte';
describe('Counter component', function () {
// tests are the same
});
Команды
Есть четыре команды для запуска из cli:
dev
: запустить vitest в режиме разработкиrelated
: запускает тесты для списка исходных файловrun
: запустить тесты один разwatch
: режим по умолчанию, такой же, как при запуске vitest. Наблюдает за изменениями, а затем повторно запускает тесты.
Модификаторы тестов
Существуют модификаторы для тестов, которые изменят способ выполнения ваших тестов.
.only сосредоточится на одном или нескольких тестах, пропустив остальные
.skip пропустит указанный тест
.todo пометит тест, которq будtn реализован позже
.concurrently будет запускать непрерывные тесты, помеченные как concurrent параллельно. Этот модификатор можно комбинировать с предыдущими. Например:
it.concurrently.todo("сделать что-то асинхронное")
Assertions
Vitest поставляется с assertions, совместимыми с chai и jest
expect(true).toBeTruthy() //ok
expect(1).toBe(Math.sqrt(4)) // false
Список доступных assertions см. в документации по API.
Покрытие
Для отчетов о покрытии нам нужно будет установить c8 и запустить тесты с флагом --coverage
.
npm i -D c8
npx vitest --coverage
Это даст нам хороший отчет о покрытии.
Папка coverage будет создана в корне проекта. Вы можете указать желаемый тип вывода в файле конфигурации.
import { defineConfig } from 'vite';
import { svelte } from '@sveltejs/vite-plugin-svelte';
// https://vitejs.dev/config/
export default defineConfig({
plugins: [svelte({ hot: !process.env.VITEST })],
test: {
globals: true,
environment: 'jsdom',
coverage:{
reporter:['text', 'json', 'html'] // change this property to the desired output
}
},
});
UI
Вы также можете запустить vitest с помощью пользовательского интерфейса, который поможет вам визуализировать выполняемые тесты и их результаты. Давайте установим необходимый пакет и запустим его с флагом --ui.
npm i -D @vitest/ui
npx vitest --ui
Мне нравится этот интерфейс. Он даже позволяет вам прочитать код тестов и открыть его в редакторе.
Больше возможностей
Vitest поставляется со многими другими функциями, такими как тестирование снепшотами, мокинг, фальшивые таймеры и многое другое, что вы можете знать из других библиотек тестирования.
Переход на Vitest (из проекта Vite с использованием jest)
Если вы работаете над небольшим проектом или только начинаете его, вам может потребоваться адаптировать файл конфигурации, и на этом все. Если вы используете мокинг функции, Vitest использует TinySpy, а для фальшивых таймеров — @sinonjs/fake-timers. Проверьте совместимость. Кроме того, не забудьте импортировать {vi} из vitest, если вы будете его использовать. Еще одна вещь, которую вам может понадобиться настроить, — это установочный файл. Например, чтобы использовать сопоставители jest-dom, мы можем создать установочный файл.
import '@testing-library/jest-dom'
и объявим его в нашем конфигурационном файле.
export default defineConfig(({ mode }) => ({
// ...
test: {
globals: true,
environment: 'jsdom',
setupFiles: ['<PATH_TO_SETUP_FILE>']
}
}))
Вот пример миграции VitePress на Vitest. (Есть некоторые изменения в ts-config, но вы можете увидеть, где добавлен vitest, и файл vitest.config.ts)
Последние мысли
Несмотря на то, что Vitest все еще находится в разработке, он выглядит очень многообещающе, и тот факт, что они сохранили API, очень похожий на Jest, делает миграцию очень плавной. Он также поставляется с поддержкой TypeScript (без пакета внешних типов). Использование одного и того же файла конфигурации (по умолчанию) позволяет очень быстро сосредоточиться на написании тестов. Я с нетерпением жду v1.0.0
Ustas4
Жаль, что переводная статья. Я читаю код и не понимаю главного: вижу текст кода, а название и тип файла где? Его нет. Файловая структура какая?
Я получил задание внедрить автотесты UI. Ищу подходящий материал. А тут не могу разобраться в принципе , чтоб сделать proof of concept.
С селениум 4 такого не происходит.
VanishMax
Vitest – инструмент для unit-тестирования. Если вы рассматриваете end-to-end тестирование, то можете посмотреть в сторону Playwright или Cypress
qmzik Автор
Компоненты приведены на примере Sveltejs, соответственно расширение .svelte. Для тест файлов .test.js или .test.ts (кому-то ещё нравится .spec вместо .test) в зависимости есть ли у вас в проекте typescript. Структура unit тестов обычно зависит от структуры самого проекта, часто бывает, что полностью повторяет её