ããã«ã¡ã¯ï¼ããã³ãã¨ã³ãã®ä¸çã¯å¸¸ã«é²åãã¦ãã¦ãæ°ããæè¡ããã¼ã«ã次ã ã¨ç¾ããããããããªä¸ããã¹ããã¬ã¼ã ã¯ã¼ã¯ã®é¸æã¯ãã¦ã§ãã¨ã³ã¸ãã¢ã®æ è·¯ã«ãããéè¦ãªæ±ºæã ãä»åã¯ãJavaScript/TypeScriptã®éçºã«ããã¦ãæ°ããªå¯è½æ§ãç§ãããã¹ãã©ã¤ãã©ãªãVitestãããç´¹ä»ãããã
Jestã«ä¼¼ã¦ãããã©ãããã«ããã¤ãã®ç¹é·ãåããVitestããã®è¨äºã§ã¯ãVitestã®å°å ¥ããåºæ¬çãªä½¿ãæ¹ãããã«ã¯çºå±çãªæ©è½ã¾ã§ãæãä¸ãã¦ããããããããVitestã®èªæµ·ã«åºãåãã¡ã«ãå°ãã§ãå½¹ç«ã¤æ å ±ãæä¾ã§ããã°ã¨æã£ã¦ãã
æ¬è¨äºã¯ãNext.jsã¨ã®é£æºãViteã®æ©æµãåããVitestã®ç´ æ´ããããä½é¨ãããã¨èãã¦ããã¦ã§ãã¨ã³ã¸ãã¢ã®ããã«ç¹å¥ã«ç¨æãããè¹åºã®æºåã¯ããããï¼ããã§ã¯ãVitestã®ä¸çã¸ã®èªæµ·ãå§ãããï¼
âã¯ãã¡ã®AIããã«èãã¦ãããã¾ãããã¡ãã£ã¨å¼µãåãããã
ä»äºã§ä½¿ãæ©ä¼ããã£ãã®ã§ãJavaScript/TypeScriptã®ãã¹ããã¬ã¼ã ã¯ã¼ã¯(ã©ã¤ãã©ãª)ã§ããVitestã«å ¥éããããã®è¨äºã§ã¯ãæ¢ã«ä»è¨èªã§ã®ãã¹ãçµé¨ãããã¦ã§ãã¨ã³ã¸ãã¢ã®ããã®Vitestå°å ¥ã®æé ãåºæ¬çã»çºå±çæ©è½ã®ç´¹ä»ãVitestã«å¾ãæ触ãªã©ãã¡ã¢ãããã®ã ãçè ã¯æè¿Next.jsã«ããããã³ãã¨ã³ãéçºãæ¬æ ¼çã«ã¹ã¿ã¼ããããããã£ãªã¢çã«ã¯ããã¯ã¨ã³ããã¡ã¤ã³ã®ã¨ã³ã¸ãã¢ã ã
ãã®è¨äºã¯ã覧ã®ã©ã¤ãã©ãªãã¼ã¸ã§ã³ã§ãéããã¾ãã
- Vite 0.34.6
- Next 13.5.6
- Vitestã¨ã¯ä½ã
- å ¥é: Vitestã®å°å ¥
- åºç¤: Vitestã§ãã¹ããæ¸ã
- åºæ¬: Vitestã®matcherã«ç¿çãã
- çºå±: 便å©ãªæ©è½
- ã¾ã¨ã
Vitestã¨ã¯ä½ã
Vitestã¯ãJavaScript(JS)/TypeScript(TS)ã®ããã®ãã¹ãã©ã¤ãã©ãªã ããã®ã©ã¤ãã©ãªã使ã£ã¦ãã¹ããæ§æãããã¨ã§npmãªã©ãçµç±ãã¦ãã¹ããå®è¡ã§ããã
åæ§ã®ãã¹ãã©ã¤ãã©ãªã¨ãã¦JestãããããVitestã¯Jestã¨ã»ã¼äºæã§ãããã¨ãæ²ãã¦ãããããJestã«æ¢ã«æ £ã親ããã ã¦ã¼ã¶ã«ã¨ã£ã¦ã¯Vitestã®å°å ¥ã¯å®¹æã§ãããã
Jest Compatible Expect, snapshot, coverage, and more - migrating from Jest is straightforward.
Vitestã®ã¡ãªãã
Vitestã¯Jestãããå¾çºã§ãããªãããã¨ã³ã¸ãã¢ã«æ¯æããããããã¤ãã®ç¹é·ãåãã¦ããã
- ã¼ãã³ã³ãã£ã°ã§ESM(ECMAScript Module)ã«å¯¾å¿ãã
- ããã¤ãã®ãã¬ã¼ã ã¯ã¼ã¯ã¯å é¨çã«ESMãå¼ã³åºãã¦ãããããããã®ãããªå ´åãJestãå©ç¨ããã¨ãã¯ç ©éãªè¨å®ãå¿ è¦ã«ãªãããVitestã§ã¯æåããESMã«å¯¾å¿ãã¦ãããViteãå©ç¨ãã¦é©åãªãã³ãã«ãå®è¡ãããã
- é«é
- Vitestã¯Viteã«ä¾åãããViteãããã¯ã¨ã³ãã«ãããããã§ãé«éå®è¡ã¨ãã£ãViteãæã¤ããã©ã¼ãã³ã¹ä¸ã®åªä½ãæ軽ã«å¾ãããã
- CIã«ããã¦ã¯ãã¹ãé度ã¯éè¦ã§ãããCIã®é度ã¯ãã®ã¾ã¾ããªããªã¼ã¹ãã¼ãã«å½±é¿ããã
- Hot Module Reload(HMR)ãæ´»ç¨ãããwatchã¢ã¼ãã§åä½ããã©ã³ãã¼
Vitestã®ãã¡ãªãã
Vitestã¯ãã®æ§è³ªä¸ãViteãä¾åæ§ã¨ãã¦æã¤ãããä¾åæ§ã極éã¾ã§åãè©°ãããå ´åã«ã¯ä¸é©ãããããªãããã ãæçµçãªææç©ã«ãã³ãã«ããããã¡ã¤ã«ã«ã¯å½ç¶ãã®ãããªä¾åæ§ã¯å«ã¾ããªãã
ã¾ããæ´å²çã«ã¯Jestã®ã»ããé·ã使ããã¦ãã¦ãããäºä¾ãå¨è¾ºç¥èã«ä¸å®ããã人ããããããããªãããããVitestã¯Jestã¨ã»ã¼äºæã§ãããJestã®ãã¯ããã¯ãã»ã¼ãã®ã¾ã¾éç¨ããã ããã
å ¥é: Vitestã®å°å ¥
ä»åã¯å ¸åçãªä¾ã¨ãã¦Next.jsããã¸ã§ã¯ãã«Vitestãå°å ¥ããæé ã説æãã(æ®éã®Reactããã¸ã§ã¯ãã¨å¤§å·®ãªãã)ãæ¢ã«å°å ¥ãæ¸ãã§ããå ´åã¯ãã®ã»ã¯ã·ã§ã³ãé£ã°ãã¦ããã
ã¾ããä»åã¯ã©ã¤ãã©ãªããã¼ã¸ã£ã¨ãã¦pnpmã使ã£ã¦ããããåç°å¢ã«ãã£ã¦é©åãªã³ãã³ãã©ã¤ã³ã«èªã¿æ¿ãã¦ã»ããã
ããã±ã¼ã¸ã¤ã³ã¹ãã¼ã«
Vitestãå°å
¥ããã«ã¯ãvitest
ããã±ã¼ã¸ã«å ãã¦ãDOMãReact Componentããã¹ãããããã®è¿½å ã©ã¤ãã©ãªãã¤ã³ã¹ãã¼ã«ãã:
% npm install -D vitest @vitejs/plugin-react @testing-library/jest-dom @testing-library/react @testing-library/user-event jsdom typescript
package.json
ã«ãã¹ãå®è¡ç¨ã¹ã¯ãªãããè¨è¼ãã
次ã«ãpnpm run test
ã¨ãã£ãã³ãã³ãã§ãã¹ããå®è¡ã§ããããã«package.json
ã«è¿½è¨ãã:
{ "scripts": { + "test": "vitest --watch --ui --coverage.enabled=true", + "test:ci": "vitest --coverage.enabled=true --ci", } }
Vitestã®åæè¨å®ãvitest.config.js
ã«è¨å®ãã
Vitestã¯ã¼ãã³ã³ãã£ã°ã§å©ç¨å¯è½ã ããããã§ã¯ç¹å®ã®ã©ã¤ãã©ãªãå
¨ãã¹ããã¡ã¤ã«ã§importãããã®ã§ãã®ããã®è¨å®ãè¡ããããVitestã®è¨å®ã¯ããã¸ã§ã¯ãã«ã¼ãã®vitest.config.js
ã«è¨è¿°ããã
/// <reference types="vitest" /> import react from '@vitejs/plugin-react' import { defineConfig } from 'vitest/config' export default defineConfig({ plugins: [react()], test: { globals: true, environment: 'jsdom', setupFiles: './test/setup.ts', // å ´æã¯ã©ãã§ãããããã¹ãã¨æããã°ãã }, resolve: { alias: { '@': __dirname + '/src', }, }, })
ä»åã¯DOMã®ããã®matcher(å¾è¿°)ãä¾çµ¦ãã¦ããã@testing-library/jest-dom
ãå
¨ãã¹ããã¡ã¤ã«ã§å©ç¨ããããããtest/setup.ts
ãèªã¿è¾¼ã¾ãã¦ããã
å®éã®test/setup.ts
ã«ã¯ä»¥ä¸ã®ããã«è¨è¿°ãã:
import '@testing-library/jest-dom';
@testing-library/jest-dom
ã¯importããã ãã§å¹åãçºæ®ãããããããã ãã§ããã
次ã®ã»ã¯ã·ã§ã³ã§ã¯ãå®éã«Vitestãæä¾ããDSLãç¨ãã¦ãã¹ããæ§æããã
åºç¤: Vitestã§ãã¹ããæ¸ã
ãã®ã»ã¯ã·ã§ã³ã§ã¯ãVitestãæä¾ããDSLãå©ç¨ããåºæ¬çãªmatcherã«ãããã¹ããæ§æããæ¹æ³ã説æããã
Vitestã¯Jeståæ§ãdescribe
ãtest
ã¨ãã£ãDSLãæä¾ãããã¨ã§æ§é çã«ãã¹ããæ¸ãããJestã«æ
£ã親ããã§ããå ´åã¯ã»ã¼åãã ããã
Vitestã®ãã¡ã¤ã«æ§æ
Vitestã§ã¯ããã¹ãã³ã¼ããã©ãã«é
ç½®ãããã¯ããªãæè»ã«æ±ºãããã¨ãã§ãããããã©ã«ãã§ã¯**/*.{test,spec}.?(c|m)[jt]s?(x)
ã«ããããããã¡ã¤ã«ããã¹ãã®å¯¾è±¡ã«ãªã(Configuring Vitest | Vitest ãåç
§)ãä»åã¯ãã¹ããã¡ã¤ã«ã./test/
以ä¸ã«é
ç½®ãããã¡ã¤ã«åã¨ãã¦foobar.spec.tsx
ã®ããã«æ¸ããã¨ã¨ããããã®ã·ãã¥ã¨ã¼ã·ã§ã³ã§ããã°ç¹ã«è¿½å ã®è¨å®ã¯ä¸è¦ã ã
Vitestã®DSL
æåã®ãã¹ããæ¸ãã¦ã¿ããã./test/foobar.spec.ts
ã«ã以ä¸ã®ããã«è¨è¿°ãã:
import { describe, expect, it, vitest } from 'vitest'; describe("Number 42", () => { it("is 42", () => { expect(42).toBe(42); }); });
Vitestã§ã¯ããã¹ããã¡ã¤ã«ä¸ã«describe
ã§ãã¹ããã°ã«ã¼ãã³ã°ããit
ã§åãã¹ããè¨è¿°ãã¦ãããit
ã®ä¸ã§ã¯æçµçã«expect().toFooBar
ã¨ããå½¢å¼ã§å¤ã®ãã¹ããè¡ãããã®.toFooBar
ã®é¨åãmatcherã¨å¼ã¶ãmatcherã¯ãã©ã°ã¤ã³ã«ãã追å ã§ããã
ãããã®describe
ãit
ãexpect
ãããã¦matcherã¯Vitestãæä¾ããDSLã ãã¡ãªã¿ã«ãit
ã¯test
ã®ã¨ã¤ãªã¢ã¹ãªã®ã§ãæ
£ãã¦ããã»ãã§æ¸ãã¦ããã
Vitestãå®è¡ãã
Vitestãå®è¡ããã«ã¯ãpnpm run test
ãå®è¡ãããããã»ã©package.json
ã§test
ããã¨vitest --watch --ui
ãåä½ããããã«è¨å®ãã¦ãããããèªåçã«ãã©ã¦ã¶ãèµ·åããã¦ã©ããã¢ã¼ãã«å
¥ãã
ãã©ã¦ã¶ã§ãã¹ãç¶æ³ã確èªã§ããè½ã¡ã¦ãããã¹ãã®ã½ã¼ã¹é¨åãè¦ãããã®ãã¨ã¦ã便å©ã ã
ã¾ããpnpm run test:ci
ãå®è¡ããã¨CIã¢ã¼ãã§ãã¹ããå®è¡ãããããã®ã¢ã¼ãã§ã¯ãã¹ãããã·ã§ãããã¹ã(å¾è¿°)ãè¡ã£ãå ´åã«èªåçã«ã¹ãããã·ã§ãããæ´æ°ããããã¹ããè½ã¨ãã
ããã§Vitestã®åºæ¬çãªæ§æã¯æããããã¯ãã ã次ã®ã»ã¯ã·ã§ã³ã§ã¯ãVitestãæã¤ãã¾ãã¾ãªmatcherãç¨ãã¦ç®çã®ãã¹ããå®è¡ããã
åºæ¬: Vitestã®matcherã«ç¿çãã
Vitestã§ã¯ãä»è¨èªã¨åæ§ã«matcherãç¨ãã¦å¤ã®æ¯è¼ãè¡ãããã®ã»ã¯ã·ã§ã³ã§ã¯ããã®ãã¡åºæ¬çãªãã®ãç´¹ä»ããã
åºæ¬çãªå¤ã®æ¯è¼
Vitestã¯ä»¥ä¸ã®ãããªmatcherãç¨æãã¦ãã(ããã¯ã»ãã®ä¸é¨ã§ãã)ã
import { describe, expect, it, vitest } from 'vitest'; describe("matcher", () => { it("ç価æ§æ¯è¼ã§ãã", () => { // toBeã¯Object.isãå©ç¨ãã expect(42).toBe(42); expect("foo").toBe("foo"); // XXX: floating pointã«å¯¾ãã¦toBeã使ãã®ã¯ãã°ã®ãã¨ãªã®ã§é¿ãã expect(3.14).toBe(3.14); }); it("notã§å転ã§ãã", () => { expect(true).not.toBe(false); }); it("ãªãã¸ã§ã¯ãã®ç価æ§ãæ¯è¼ã§ãã", () => { const d1 = { x: 42, y: 10, }; const d2 = { x: 42, y: 10, }; expect(d1).not.toBe(d2); expect(d1).toEqual(d2); }); it("大å°æ¯è¼ã§ãã", () => { expect(42).toBeGreaterThanOrEqual(42); expect(42).toBeGreaterThan(41); expect(42).toBeLessThan(43) expect(42).toBeLessThanOrEqual(42) }); it("ãµã¤ãºãæ¯è¼ã§ãã", () => { expect("foo").toHaveLength(3); expect([1, 2, 3, 4, 5]).toHaveLength(5); }); it("truthy/falthyãæ¤æ»ã§ãã", () => { expect([]).toBeTruthy(); expect("").toBeFalsy(); }); it("Regexã«ããããããæ¤æ»ã§ãã", () => { expect("panamabanana").toMatch(/^(.a)+$/) expect("panamabanana").toMatch("banana") }); it("éåæå¦çã®çµæãæ¤æ»ã§ãã", async ({ expect }) => { const calcAnswer = async () => { return Promise.resolve(42) }; expect(calcAnswer()).resolves.toBe(42); }); it("throwãæ¤æ»ã§ãã", () => { const thrower = () => { throw "boom" }; expect(thrower).toThrow("boom"); }); });
ãã¹ããå®è¡ãããã¨åãã¹ããã¨ã®çµæã表示ãããã
Reactã³ã³ãã¼ãã³ãã®æ¯è¼
Vitestã§ã¯ãããã¤ãã®ãã©ã°ã¤ã³ãå©ç¨ãããã¨ã§Reactã³ã³ãã¼ãã³ããæå³ããéãã«ã¬ã³ããªã³ã°ããã¦ãããã©ãããªã©ããã¹ãã§ããã
ã¾ãä¾ã¨ãã¦ã以ä¸ã®ãããªã³ã³ãã¼ãã³ããããã¨ä»®å®ãã:
export default function Message(props: {message: string}) { <span className="warning">{props.message}</span> }
ãã¹ãä¸ã§ã¯ããããã¥ã¡ã³ããã«ã³ã³ãã¼ãã³ããã¬ã³ãã¼ãããã®æ§åã観å¯ããã¨ããã¹ã¿ã¤ã«ã§ãã¹ããè¡ããã³ã³ãã¼ãã³ããã¬ã³ãã¼ããã«ã¯ã@testing-library/react
ãæä¾ããrender
ãå©ç¨ãã:
import { fireEvent, render, screen } from "@testing-library/react"; import { describe, expect, it, vitest } from 'vitest'; describe("Message", () => { it("can be rendered", () => { render(<Message message="Hello, Vitest!" />) }); });
@testing-library/react
ã¯ã以ä¸ã®ãããªAPIãæä¾ãã:
render
- React ã³ã³ãã¼ãã³ããã¬ã³ãã¼ãã
- ããã©ã«ãã§ã¯
body
ã®ä¸ã«div
ãä½ãããããã«ã¬ã³ãã¼ããã
screen
- Reactã³ã³ãã¼ãã³ããã¬ã³ãã¼ãããã³ã³ããããè¦ç´ ãæ¢ãããããããã®ãªãã¸ã§ã¯ã
fireEvent
- ã¯ãªãã¯ã¤ãã³ããªã©ã®ã¤ãã³ããçºç«ããããã«ãã¼
- æ¬æ ¼çã«ã¤ãã³ããå«ããã¹ããããããå ´åã¯ããããªãããª
@testing-library/user-event
ã使ãã¹ãã¨ããã¦ãã
screen
ã¯ä»¥ä¸ã®ãããªã¡ã½ãããæä¾ããè¦ç´ ãæ¢ãæå©ãããã:
getByRole
getByLabelText
getByPlaceholderText
getByText
getByDisplayValue
ã¾ãgetBy
ã®ããªã¨ã¼ã·ã§ã³ã¨ãã¦queryBy
ãgetAllBy
ãªã©ãç¨æããã¦ãã(getBy
ã·ãªã¼ãºã¯ãããããªãå ´åã«throwããããqueryBy
ã·ãªã¼ãºã¯nullãè¿ãã«ã¨ã©ã¾ã)
ã³ã³ãã¼ãã³ããã¬ã³ãã¼ããã¦ããããæ³å®éãã«ãªã£ã¦ããããæ¤æ»ããã«ã¯ãscreen
ãæ´»ç¨ãããä¾ãã°screen.findByText
ã使ãã¨ããã¹ãã使ã£ã¦è¦ç´ ãªã©ãæ¤ç´¢ã§ãããããã«éããæ¤ç´¢ç³»APIã¯éåæã«çµæãè¿ããã®ãå¤ããããasync
/await
ã使ã£ã¦å¦çããã
import { fireEvent, render, screen } from "@testing-library/react"; import { describe, expect, it, vitest } from 'vitest'; describe("Message", () => { it("can be rendered", async ({ expect }) => { render(<Message message="Hello, Vitest!" />); const found = await screen.findByText("Hello, Vitest!"); expect(found).toBeInTheDocument(); expect(found).toHaveClass("warning"); }); });
toBeInTheDocument
ã¯@testing-library/jest-dom
ãä¾çµ¦ãã¦ããmatcherã§ãåé ã®setup.ts
ã§ãããããimportæ¸ã¿ã§ããã
jest-dom
ãä¾çµ¦ããmatcherã®ãã¡ãã使ããããªãã®ã¯ä»¥ä¸ã®éã:
toBeInTheDocument
- ãããããã¥ã¡ã³ãä¸ã«ãããã¨ãæ¤è¨¼ãã
toHaveClass
- è¦ç´ ãç¹å®ã®ã¯ã©ã¹ãæã£ã¦ãããã¨ãæ¤è¨¼ãã
- åæ§ã«
toHaveAttribute
ãtoHaveStyle
ãtoHaveDisplayValue
ãtoHaveTextContent
ãªã©ããã
toBeVisible
- ãã©ã¦ã¶ä¸ãããã®è¦ç´ ãå¯è¦ã§ãããã¨ãæ¤è¨¼ãã
opacity
ãdisplay
å±æ§ãªã©ãèæ ®ãã¦ããã
Next.jsç¹æã®å¦ç
Next.jsã®å ´åã¯ãã¬ã¼ã ã¯ã¼ã¯ã§ãããã¨ããè¤æ°ã®ã³ã³ãã¼ãã³ããå調ãã¦ããããã®ã¾ã¾ã³ã³ãã¼ãã³ãã®ãã¹ããã§ããªãå ´åãããã
èªåã®å ´åã¯ã«ã¼ã¿ã¼ã¾ããã§ã¨ã©ã¼ãçºçããã®ã§ãé¢é£ç®æãåãé¢ãå¦çãè¡ã£ãã
// routerã¾ããã§ã¨ã©ã¼ãåºããã¨ãããã®ã§ãæåã«mockãç¨æãããåç´ãªã³ã³ãã¼ãã³ãã§ããã°å¿ è¦ãªãã¯ã vitest.mock("next/navigation", () => ({ useRouter() { return { prefetch: () => null }; } }));
çºå±: 便å©ãªæ©è½
ãã®ã»ã¯ã·ã§ã³ã§ã¯ãç¥ã£ã¦ããã¨ä¾¿å©ãªçºå±çãªè©±é¡ãæä¾ããã
todo
describe
ãit
ã«ã¯.todo
ã¡ã½ãããçãã¦ããããããå¼ã¶ã¨ãã¹ããã¹ããããããããã
describe("Message", () => { // ãã®ãã¹ããã¹ããããã it.todo("can be rendered", async ({ expect }) => { render(<Message message="Hello, Vitest!" />); const found = await screen.findByText("Hello, Vitest!"); expect(found).toBeInTheDocument(); expect(found).toHaveClass("warning"); }); });
beforeEach
/ afterEach
ä»ã®ãã¹ããã¬ã¼ã ã¯ã¼ã¯åæ§ã«ããã¹ãã®åå¾ã«ç¹å®ã®å¦çãè¡ãæ©è½ãVitestã«ã¯ç¨æããã¦ããã
import { beforeEach } from 'vitest' beforeEach(async () => { // Clear mocks and add some testing data after before each test run await stopMocking() await addUser({ name: 'John' }) })
beforeEach
ã¯it
åä½ã§å®è¡ããããbeforeAll
ã¯ãã¹ããã¡ã¤ã«åä½ã§å®è¡ããããåæ§ã«ãã¦afterEach
/ afterAll
ãåå¨ãããã¢ãã¯ã®ã»ããã¢ããããã¹ããã¼ã¿ã®ã¯ãªã¼ã³ã¢ãããªã©ã«ä½¿ãã¨è¯ãã ããã
ã¢ãã¯
Vitestã¯ã¢ãã¯ãæä¾ãã¦ããã
ãã¡ãã¯å ¬å¼ã«ãã¼ãã·ã¼ããç¨æããã¦ããã®ã§ããããè¦ãã¨è¯ãã ããã
ã«ãã¬ãã¸
vitest --watch --ui --coverage.enabled=true
ã®ããã«è¨å®ãã¦ããã¨ãå
¨èªåã§åæã«ã«ãã¬ãã¸ãåã£ã¦ãããã®ã§ãã¨ããããæå¹ã«ãã¦ããã¨è¯ãã
Snapshot testing
Vitestã§ã¯ã¹ãããã·ã§ããã使ã£ããã¹ããå¯è½ã ãã¹ãããã·ã§ãããã¹ãã§ã¯ããã¹ã対象ã®å¤ãå¤åãã¦ããªããã¨ãä¿è¨¼ããããã®ãã¯ããã¯ã ãä¸è¬ã®ãã¹ãã§ã¯å¤ãä¸å®ã®æ¡ä»¶ãæºãããã¨ãæ¤è¨¼ããããã¹ãããã·ã§ãããã¹ãã§ã¯ãããååã®æ£å¸¸ãªãã¹ãããå¤åãã¦ããªããã¨ãæ¤è¨¼ããã
ã¹ãããã·ã§ãããã¹ãã¯ãåæã«å 容ãå¤åãã¦ã¯å°ã対象ãä¾ãã°ã³ã³ãã¼ãã³ãã®ã¬ã³ããªã³ã°çµæãAPIã®ã¬ã¹ãã³ã¹ãªã©ã«å¯¾ãã¦é©ç¨ãããã
Vitestã§ããå¤ãã¹ãããã·ã§ããã¨åè´ãã¦ãããã©ãããæ¤è¨¼ããã«ã¯ãtoMatchSnapshot
ãå©ç¨ãã:
import { fireEvent, render, screen } from "@testing-library/react"; import { describe, expect, it, vitest } from 'vitest'; describe("Message", () => { it("can be rendered", async ({ expect }) => { render(<Message message="Hello, Vitest!" />); const found = await screen.findByText("Hello, Vitest!"); expect(found).toBeInTheDocument(); expect(found).toHaveClass("warning"); expect(found).toMatchSnapshot(); }); });
ã¹ãããã·ã§ãããåå¨ããªãå ´åãVitestã¯ãã¹ããã¡ã¤ã«ã¨åãé層ã«ãã£ã¬ã¯ããªãä½æãã¦æ°è¦ã«ã¹ãããã·ã§ãããä¿åããã
ãã¹ãçµæãã¹ãããã·ã§ããã¨ç°ãªãå ´åãVitestã¯ãã¹ãã失æãããã
ã¹ãããã·ã§ãããæ´æ°ãããã«ã¯ãã¹ãçµæã®ç»é¢ã§u
ãæ¼ä¸ããã
ã¡ãªã¿ã«ã¹ãããã·ã§ããã¯Web UIãããæ´æ°ãæ示ã§ããã®ã§ããã¡ãã®ã»ãã便å©ã ããã
pnpm test:ci
ãªã©ã§VitestãCIã¢ã¼ãã§å®è¡ããã¦ããå ´åã¯ãã¹ãããã·ã§ããã®æ´æ°ã¯è¡ãªããããã¦ã¼ã¶ã¸ã®æ示ã ãã表示ãããã
CIã¸ã®å°å ¥
ä»ã®ãã¹ããã¼ã«åæ§ãVitestã¯GitHub Actionsã¨ãã£ãCI/CDåºç¤ã§å©ç¨ã§ãããç¹ã«å½¹ç«ã¡ãããªè¨å®ã¯ä»¥ä¸ã®éã:
- ãã£ãã·ã¥
- è¨å®ã¨ãã¦
cache.dir
ã«ãã£ãã·ã¥å ãã£ã¬ã¯ããªãæå®ããã¨ãVitestã¯ãã£ãã·ã¥ã§ãããã¡ã¤ã«ãããã«ä¿åããããã«ãªã(Vitestã¯ããã©ã«ãã§ãã£ãã·ã¥ãã)ã - GitHub Actionsã®
cache
ã¢ã¯ã·ã§ã³ãªã©ãå©ç¨ãã¦ããããã£ãã·ã¥ããã¨ãã¹ãã®é«éåãæå¾ ã§ããã
- è¨å®ã¨ãã¦
- ã«ãã¬ãã¸
- ã«ãã¬ãã¸ãGitHub Actionsã«å ±åããactionãåå¨ããã
- https://github.com/marketplace/actions/vitest-coverage-report
ã¾ã¨ã
ãã®è¨äºã§ã¯ãJS/TSåããã¹ãã©ã¤ãã©ãªã§ããVitestã«ã¤ãã¦ã®ç°¡æ½ãªèª¬æããå§ãããã¹ãã®åºç¤ããçºå±çãªè©±é¡ã¾ã§ãä¸ç´ç·ã«è§£èª¬ãããããå°éçã»è©³ç´°ãªè©±é¡ã¯å ¬å¼ã®ããã¥ã¡ã³ããæ¤ç´¢ãããã¨ãããããããã