Kodėl apskritai kalbame apie testavimo įrankių keitimą?
Jei dirbi su Vue ekosistema, tikriausiai pastebėjai, kad pastaraisiais metais vis dažniau pasigirsta kalbų apie Vitest. Jest ilgą laiką buvo neginčijamas testavimo įrankių karalius JavaScript pasaulyje, bet dabar situacija keičiasi. Ir ne be priežasties.
Pirmiausia reikia suprasti kontekstą. Vue 3 atėjo su Vite – naująja kartos build įrankiu, kuris pakeitė žaidimo taisykles. Jis greitesnis, paprastesnis konfigūruoti ir tiesiog malonesnis naudoti nei tradicinis Webpack. Problema ta, kad Jest buvo sukurtas senesnių įrankių eroje ir su Vite dirba… na, pasakykime, ne idealiai.
Čia ir ateina Vitest – testavimo framework’as, kuris gimė su Vite DNR. Jis naudoja tą pačią konfigūraciją, tą patį plugin sistemą ir net tą patį resolver’į. Skamba patraukliai, tiesa? Bet ar tai reiškia, kad Jest reikia išmesti į šiukšlyną? Ne taip greitai.
Jest stipriosios pusės, kurias vis dar verta įvertinti
Pradėkime nuo to, kas Jest daro gerai. Šis įrankis egzistuoja nuo 2014 metų ir per tą laiką subrandino tikrai solidžią ekosistemą. Jei turi problemą, tikėtina, kad kažkas jau ją sprendė ir parašė apie tai Stack Overflow.
Dokumentacija yra išsami ir kruopščiai aprašyta. Yra milijonai pamokų, video, straipsnių – praktiškai bet kokią problemą gali išspręsti per kelias minutes googlindamas. Tai nėra mažmožis, ypač kai dirbi su komanda, kurioje yra skirtingo lygio specialistų.
Jest snapshot testavimas yra fenomenalus. Jei testuoji komponentus su sudėtinga struktūra, galimybė tiesiog „užfiksuoti” kaip jie atrodo ir vėliau palyginti pokyčius yra neįkainojama. Taip, Vitest irgi turi snapshots, bet Jest šioje srityje turi daugiau patirties ir geriau apdorotų edge case’ų.
Dar vienas dalykas – code coverage. Jest turi integruotą Istanbul, ir viskas veikia iš dėžės. Nereikia nieko papildomai konfigūruoti, tiesiog paleidi su --coverage flag’u ir gauni gražų ataskaitą. Mocking sistema taip pat yra labai galinga – gali mock’inti viską nuo modulių iki timer’ių.
Kur Jest pradeda girgždėti dirbant su Vue 3
Dabar apie ne tokias gražias puses. Jei bandei setup’inti Jest su Vue 3 ir Vite projektu, žinai, kad tai gali virsti tikru galvos skausmu. Tau reikia įdiegti @vue/test-utils, tada babel-jest, sukonfigūruoti transform’us, pridėti vue-jest, ir dar dešimt kitų dalykų.
Problema ta, kad Jest nesupanta ES modulių natūraliai. Jam reikia Babel, kad transformuotų kodą į CommonJS. Tai prideda papildomą sluoksnį, kuris lėtina viską ir kartais sukelia keistų klaidų. Ypač kai naudoji modernius JavaScript features arba TypeScript.
Greitis – štai kur Jest tikrai atsilieka. Kai projektas auga, testai pradeda veikti vis lėčiau. Taip, yra cache’inimas, yra paralelizavimas, bet vis tiek. Jei turi 500+ testų, gali eiti kavos, kol jie pasibaigs. O jei nori watch mode – pasiruošk, kad po kiekvieno pakeitimo lauksi 5-10 sekundžių.
Konfigūracija su Vite yra tiesiog skausminga. Tu turi vieną konfigūraciją Vite (vite.config.js), kitą Jest’ui (jest.config.js), ir jos nekalba viena su kita. Tai reiškia, kad alias’us, plugin’us ir kitus dalykus turi dubliuoti abiejose vietose. Kai kas nors keičiasi, turi atminti atnaujinti abi.
Vitest įžengia į sceną su nauju požiūriu
Vitest buvo sukurtas Anthony Fu, kuris yra Vue core team narys, tad jis puikiai supranta Vue ekosistemos poreikius. Pagrindinis Vitest pranašumas – jis naudoja Vite po gaubtu. Tai reiškia, kad visa tavo Vite konfigūracija automatiškai veikia testuose.
Greitis yra akivaizdus nuo pirmos sekundės. Vitest naudoja esbuild transformacijoms ir Vite HMR infrastruktūrą. Praktiškai tai reiškia, kad testai startuoja beveik akimirksniu. Watch mode’e pakeitimai atspindi per milisekundes, ne sekundes. Kai dirbi su TDD arba tiesiog dažnai leidžiuoji testus, šis skirtumas yra dienos ir nakties.
API yra beveik identiškas Jest – tai buvo sąmoningas sprendimas. Jei žinai Jest, žinai ir Vitest. describe, it, expect – viskas tas pats. Tai reiškia, kad migravimas nėra baisus, ir nauji komandos nariai gali lengvai persijungti.
TypeScript palaikymas yra first-class. Nereikia jokių papildomų transform’ų ar komplikuotų setup’ų. Tiesiog rašai TypeScript testus, ir jie veikia. Tai gali skambėti kaip smulkmena, bet kai dirbi su dideliu TypeScript projektu, tai tikrai svarbu.
Praktinis setup palyginimas
Pažiūrėkime, kaip atrodo realus setup’as abiem atvejais. Su Jest tau reikia maždaug tokios konfigūracijos:
npm install --save-dev jest @vue/test-utils @vue/vue3-jest babel-jest
Tada jest.config.js:
module.exports = {
testEnvironment: 'jsdom',
transform: {
'^.+\\.vue$': '@vue/vue3-jest',
'^.+\\.(js|jsx)$': 'babel-jest',
},
moduleFileExtensions: ['js', 'json', 'vue'],
moduleNameMapper: {
'^@/(.*)$': '
},
}
Dar reikia babel.config.js ir galimas daiktas, kad susidursi su problemomis dėl ES modulių.
Su Vitest viskas daug paprasčiau:
npm install --save-dev vitest @vue/test-utils jsdom
Ir vite.config.js papildymas:
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
export default defineConfig({
plugins: [vue()],
test: {
globals: true,
environment: 'jsdom',
},
})
Matai skirtumą? Vitest naudoja tą pačią konfigūraciją, kurią jau turi. Visi tavo alias’ai, plugin’ai – viskas tiesiog veikia.
Realūs testavimo scenarijai ir kaip jie skiriasi
Pasiimkime konkretų pavyzdį – testuojame Vue 3 komponentą su Composition API. Pats testas abiem atvejais atrodys beveik identiškai:
import { mount } from '@vue/test-utils'
import { describe, it, expect } from 'vitest' // arba iš jest
import MyComponent from '@/components/MyComponent.vue'
describe('MyComponent', () => {
it('renders properly', () => {
const wrapper = mount(MyComponent, {
props: { msg: 'Hello Vitest' }
})
expect(wrapper.text()).toContain('Hello Vitest')
})
})
Bet štai kur prasideda skirtumai. Jei tavo komponente naudoji Pinia store, su Vitest tai tiesiog veikia, nes jis supranta Vite alias’us ir plugin’us. Su Jest tau reikės papildomų mock’ų ir konfigūracijos.
Async testavimas taip pat skiriasi. Vitest geriau tvarko top-level await ir dinamiškus import’us. Jest kartais gali užstrigti arba reikalauti papildomų flag’ų.
Kai testuoji komponentus su <script setup> sintakse, Vitest jaučiasi natūraliau. Jest kartais turi problemų su makro transformacijomis, ypač jei naudoji defineProps ar defineEmits su TypeScript tipais.
Migravimas: ar verta ir kaip tai padaryti
Gerai, tarkime nusprendei pereiti nuo Jest prie Vitest. Ar tai sudėtinga? Priklauso nuo projekto dydžio, bet paprastai tai nėra taip baisu, kaip gali atrodyti.
Pirmas žingsnis – įdiegti Vitest ir pašalinti Jest priklausomybes. Tada pakeisti test script’us package.json. Vietoj jest rašai vitest.
Dauguma testų veiks iš karto, nes API yra suderinamas. Bet yra keletas dalykų, į kuriuos reikia atkreipti dėmesį:
Jei naudoji jest.mock() su hoisting, Vitest turi šiek tiek kitokią sintaksę – vi.mock(). Bet funkcionalumas tas pats. Timer mock’ai taip pat šiek tiek skiriasi – vi.useFakeTimers() vietoj jest.useFakeTimers().
Global setup failai konfigūruojami kitaip. Vietoj setupFilesAfterEnv naudoji setupFiles Vitest konfigūracijoje. Snapshot’ai paprastai veikia be pakeitimų, bet verta paleisti testus ir regeneruoti juos, jei kas nors atrodo keistai.
Vienas patarimas – nedaryk visko iš karto. Pradėk nuo vieno test suite, pažiūrėk kaip veikia, tada palaipsniui migruok likusius. Gali net laikyti abi sistemas vienu metu, jei projektas labai didelis.
Performance palyginimas tikrame projekte
Skaičiai kalba patys už save. Vidutinio dydžio Vue 3 projekte su ~200 testų:
Jest: pirmas paleidimas ~15 sekundžių, watch mode pakeitimai ~3-5 sekundės. Vitest: pirmas paleidimas ~3 sekundės, watch mode pakeitimai ~200-500 milisekundžių.
Tai nėra mažas skirtumas. Tai skirtumas tarp „einu kavos” ir „iškart matau rezultatus”. Kai dirbi su TDD metodologija arba tiesiog dažnai leidžiuoji testus, šis greitis realiai keičia darbo srautą.
Memory naudojimas taip pat geresnis su Vitest. Jest turi tendenciją kaupti memory, ypač watch mode, ir kartais reikia restart’inti procesą. Vitest šioje srityje stabilesnis.
Bet reikia būti sąžingiems – jei tavo projektas mažas (kelios dešimtys testų), šis skirtumas nebus toks dramatiškas. Jest papildomos 10 sekundžių gal ir nesugriovs tavo produktyvumo.
Kas geriau tau ir tavo projektui?
Taigi, grįžtame prie pagrindinio klausimo – ką rinktis? Atsakymas, kaip dažnai būna, yra „priklauso”.
Jei pradedi naują Vue 3 projektą su Vite, Vitest yra akivaizdus pasirinkimas. Greitis, paprasta konfigūracija, puikus derinimas su ekosistema – viskas kalba už jį. Nėra prasmės kovoti su Jest setup’u, kai gali turėti kažką, kas veikia iš dėžės.
Jei turi esamą projektą su Jest, kuris veikia gerai, neskubėk. Jei testai leidžiasi pakankamai greitai ir neturi problemų, migravimas gali būti nereikalingas darbas. Bet jei jauti skausmą – lėti testai, sudėtinga konfigūracija, problemos su naujais Vue features – tada Vitest gali būti sprendimas.
Didelėms korporatyvinėms sistemoms, kur stabilumas ir patikimumas yra kritiški, Jest vis dar yra saugus pasirinkimas. Jis brandus, išbandytas milijonuose projektų, turi didžiulę community. Vitest, nors ir puikus, vis dar yra jaunesnis ir gali turėti edge case’ų.
Jei tavo komanda jau gerai išmano Jest ir neturi laiko mokytis naujų įrankių, galbūt geriau pasilikti su tuo, kas veikia. Bet jei žmonės atviri naujovėms ir vertina developer experience, Vitest tikrai verta išbandyti.
Galiausiai, abu įrankiai yra puikūs savo būdu. Jest nėra blogas, jis tiesiog buvo sukurtas kitai erai. Vitest yra natūrali evoliucija, pritaikyta šiuolaikiniam JavaScript ekosystemai. Pasirinkimas priklauso nuo tavo specifinių poreikių, projekto konteksto ir prioritetų. Bet viena aišku – Vue testavimo ateitis atrodo šviesiai su tokiais įrankiais kaip Vitest.
