Funkcje
- Konfiguracja, transformatory, resolvery i wtyczki Vite
- Wykorzystanie tej samej konfiguracji, co aplikacja, do uruchamiania testów.
- Inteligentny i natychmiastowy tryb śledzenia zmian, działający jak HMR dla testów.
- Testowanie komponentów dla Vue, React, Svelte, Lit, Marko i innych.
- Wbudowana obsługa TypeScript / JSX.
- Natywna obsługa ESM z top-level await.
- Wielowątkowe workery dzięki Tinypool.
- Obsługa testów wydajnościowych z Tinybench.
- Filtrowanie, limity czasu, współbieżność dla zestawów i testów.
- Obsługa projektów.
- Migawki zgodne z Jest.
- Chai wbudowany do asercji + API kompatybilne z Jest expect.
- Tinyspy wbudowany do mockowania.
- happy-dom lub jsdom do mockowania DOM.
- Tryb przeglądarki do uruchamiania testów komponentów w przeglądarce.
- Pokrycie kodu za pomocą v8 lub istanbul.
- Testowanie w kodzie źródłowym w stylu Rust.
- Testowanie typów za pomocą expect-type.
- Obsługa shardingu.
- Raportowanie nieprzechwyconych błędów.
Wspólna konfiguracja dla testów, rozwoju i budowania
Vitest wykorzystuje konfigurację, transformatory, resolvery i wtyczki Vite. Dzięki temu możesz używać tej samej konfiguracji, co Twoja aplikacja, do uruchamiania testów.
Dowiedz się więcej w Konfigurowanie Vitest.
Tryb obserwacji
$ vitest
Gdy zmieniasz swój kod źródłowy lub pliki testowe, Vitest inteligentnie przeszukuje graf modułów i ponownie uruchamia tylko powiązane testy, tak jak działa HMR w Vite.
vitest
domyślnie uruchamia się w trybie obserwacji
w środowisku deweloperskim i inteligentnie w trybie uruchamiania
w środowisku CI (gdy process.env.CI
jest obecne). Możesz użyć vitest watch
lub vitest run
, aby jawnie określić żądany tryb.
Uruchom Vitest z flagą --standalone
, aby działał w tle, ale nie uruchomi żadnych testów, dopóki nie zajdą zmiany. Vitest nie uruchomi testów, jeśli kod źródłowy zostanie zmieniony, dopóki nie zostanie uruchomiony test, który importuje to źródło.
Gotowe, popularne idiomy webowe
Wbudowana obsługa modułów ES / TypeScript / JSX / PostCSS.
Wątki
Domyślnie Vitest wykonuje pliki testowe w wielu procesach, wykorzystując node:child_process
poprzez Tinypool (lekki fork Piscina), co pozwala na jednoczesne uruchamianie testów. Jeśli chcesz jeszcze bardziej przyspieszyć swój zestaw testów, rozważ włączenie --pool=threads
, aby uruchamiać testy używając node:worker_threads
(należy pamiętać, że niektóre pakiety mogą nie działać z tą konfiguracją).
Aby uruchomić testy w pojedynczym wątku lub procesie, zobacz poolOptions
.
Vitest izoluje również środowisko każdego pliku, więc zmiany środowiska w jednym pliku nie wpływają na inne. Izolację można wyłączyć przez przekazanie --no-isolate
w CLI (kosztem poprawności na rzecz wydajności uruchamiania).
Filtrowanie testów
Vitest oferuje wiele sposobów na zawężenie uruchamianych testów, aby przyspieszyć testowanie i umożliwić skupienie się na rozwoju.
Dowiedz się więcej o Filtrowaniu testów.
Uruchamianie testów współbieżnie
Użyj .concurrent
w kolejnych testach, aby uruchomić je równolegle.
import { describe, it } from 'vitest';
// Dwa testy oznaczone jako współbieżne zostaną uruchomione równolegle
describe('suite', () => {
it('serial test', async () => {
/* ... */
});
it.concurrent('concurrent test 1', async ({ expect }) => {
/* ... */
});
it.concurrent('concurrent test 2', async ({ expect }) => {
/* ... */
});
});
Jeśli użyjesz .concurrent
w zestawie, każdy test w nim zostanie uruchomiony równolegle.
import { describe, it } from 'vitest';
// Wszystkie testy w tym zestawie zostaną uruchomione równolegle
describe.concurrent('suite', () => {
it('concurrent test 1', async ({ expect }) => {
/* ... */
});
it('concurrent test 2', async ({ expect }) => {
/* ... */
});
it.concurrent('concurrent test 3', async ({ expect }) => {
/* ... */
});
});
Możesz również używać .skip
, .only
i .todo
z zestawami i testami współbieżnymi. Przeczytaj więcej w Dokumentacji API.
WARNING
Podczas uruchamiania testów współbieżnych, migawki i asercje muszą używać expect
z lokalnego kontekstu testowego, aby zapewnić wykrycie właściwego testu.
Migawka
Obsługa migawek zgodna z Jest.
import { expect, it } from 'vitest';
it('renders correctly', () => {
const result = render();
expect(result).toMatchSnapshot();
});
Dowiedz się więcej w Migawka.
Kompatybilność Chai i Jest expect
Chai jest wbudowany do asercji z API kompatybilnymi z Jest expect
.
Zauważ, że jeśli używasz bibliotek innych firm, które dodają matchery, ustawienie test.globals
na true
zapewni lepszą kompatybilność.
Mockowanie
Tinyspy jest wbudowany do mockowania z API kompatybilnymi z jest
na obiekcie vi
.
import { expect, vi } from 'vitest';
const fn = vi.fn();
fn('hello', 1);
expect(vi.isMockFunction(fn)).toBe(true);
expect(fn.mock.calls[0]).toEqual(['hello', 1]);
fn.mockImplementation((arg: string) => arg);
fn('world', 2);
expect(fn.mock.results[1].value).toBe('world');
Vitest obsługuje zarówno happy-dom, jak i jsdom do mockowania DOM i API przeglądarki. Nie są one dostarczane z Vitest, będziesz musiał zainstalować je osobno:
$ npm i -D happy-dom
$ npm i -D jsdom
Następnie zmień opcję environment
w pliku konfiguracyjnym:
import { defineConfig } from 'vitest/config';
export default defineConfig({
test: {
environment: 'happy-dom', // or 'jsdom', 'node'
},
});
Dowiedz się więcej w Mockowanie.
Pokrycie kodu
Vitest obsługuje natywne pokrycie kodu za pomocą v8
oraz instrumentowane pokrycie kodu za pomocą istanbul
.
{
"scripts": {
"test": "vitest",
"coverage": "vitest run --coverage"
}
}
Dowiedz się więcej w Pokrycie kodu.
Testowanie w kodzie źródłowym
Vitest zapewnia również sposób na uruchamianie testów w kodzie źródłowym wraz z implementacją, podobnie do testów modułów w Rust.
Dzięki temu testy współdzielą to samo domknięcie co implementacje i mogą testować prywatne stany bez eksportowania. Jednocześnie skraca to cykl rozwoju.
// implementacja
export function add(...args: number[]): number {
return args.reduce((a, b) => a + b, 0);
}
// zestawy testów w kodzie źródłowym
if (import.meta.vitest) {
const { it, expect } = import.meta.vitest;
it('add', () => {
expect(add()).toBe(0);
expect(add(1)).toBe(1);
expect(add(1, 2, 3)).toBe(6);
});
}
Dowiedz się więcej w Testowanie w kodzie źródłowym.
Benchmarking Eksperymentalna funkcja
Możesz uruchamiać testy benchmarkowe za pomocą funkcji bench
poprzez Tinybench, aby porównać wyniki wydajności.
import { bench, describe } from 'vitest';
describe('sort', () => {
bench('normal', () => {
const x = [1, 5, 4, 2, 3];
x.sort((a, b) => {
return a - b;
});
});
bench('reverse', () => {
const x = [1, 5, 4, 2, 3];
x.reverse().sort((a, b) => {
return a - b;
});
});
});
Testowanie typów Eksperymentalna funkcja
Możesz pisać testy, aby wyłapywać regresje typów. Vitest zawiera pakiet expect-type
, aby zapewnić Ci podobne i łatwe do zrozumienia API.
import { assertType, expectTypeOf, test } from 'vitest';
import { mount } from './mount.js';
test('my types work properly', () => {
expectTypeOf(mount).toBeFunction();
expectTypeOf(mount).parameter(0).toMatchTypeOf<{ name: string }>();
// @ts-expect-error name is a string
assertType(mount({ name: 42 }));
});
Sharding
Uruchamiaj testy na różnych maszynach, używając flag --shard
i --reporter=blob
. Wszystkie wyniki testów i pokrycie kodu można połączyć na końcu Twojego potoku CI za pomocą polecenia --merge-reports
:
vitest --shard=1/2 --reporter=blob --coverage
vitest --shard=2/2 --reporter=blob --coverage
vitest --merge-reports --reporter=junit --coverage
Więcej informacji znajdziesz w Poprawa wydajności | Sharding
.
Zmienne środowiskowe
Vitest automatycznie ładuje zmienne środowiskowe z prefiksem VITE_
z plików .env
, aby zachować kompatybilność z testami związanymi z frontendem, zgodnie z ustaloną konwencją Vite. Aby załadować wszystkie zmienne środowiskowe z plików .env
, możesz użyć metody loadEnv
importowanej z vite
:
import { loadEnv } from 'vite';
import { defineConfig } from 'vitest/config';
export default defineConfig(({ mode }) => ({
test: {
// tryb określa, który plik ".env.{mode}" wybrać, jeśli istnieje
env: loadEnv(mode, process.cwd(), ''),
},
}));
Nieobsłużone błędy
Domyślnie Vitest przechwytuje i raportuje wszystkie nieobsłużone odrzucenia, nieprzechwycone wyjątki (w Node.js) oraz zdarzenia błędów (w przeglądarce).
Możesz wyłączyć to zachowanie, łapiąc je ręcznie. Vitest zakłada wtedy, że obsługujesz to samodzielnie i nie zgłosi błędu.
// w Node.js
process.on('unhandledRejection', () => {
// Twoja własna obsługa
});
process.on('uncaughtException', () => {
// Twoja własna obsługa
});
// w przeglądarce
window.addEventListener('error', () => {
// Twoja własna obsługa
});
window.addEventListener('unhandledrejection', () => {
// Twoja własna obsługa
});
Alternatywnie, możesz również ignorować zgłaszane błędy za pomocą opcji dangerouslyIgnoreUnhandledErrors
. Vitest nadal będzie je zgłaszać, ale nie wpłyną one na wynik testu (kod wyjścia nie zostanie zmieniony).
Jeśli musisz przetestować, czy błąd nie został przechwycony, możesz utworzyć test, który wygląda następująco:
test('my function throws uncaught error', async ({ onTestFinished }) => {
onTestFinished(() => {
// jeśli zdarzenie nigdy nie zostało wywołane podczas testu,
// upewnij się, że zostało usunięte przed rozpoczęciem następnego testu
process.removeAllListeners('unhandledrejection');
});
return new Promise((resolve, reject) => {
process.once('unhandledrejection', error => {
try {
expect(error.message).toBe('my error');
resolve();
} catch (error) {
reject(error);
}
});
callMyFunctionThatRejectsError();
});
});