Svelte 整合 vitest

tags: Svelte Testing
category: Front-End
description: Svelte 整合 vitest
created_at: 2023/04/07 02:00:00

cover image


事前準備

  • 裝好 Node.js

前言

在使用 SvelteKit 建立專案時雖然有問你要不要用 Vitest 去做測試,不過感覺給的不夠誠意,所以誕生了這篇文章。

記得先照著 Svelte 開新專案與環境設定 並且記得至少勾選 Vitest 來建立專案。


原本的長相

看看原本的提供的 src/index.test.ts,長的像下面這樣

import { describe, it, expect } from 'vitest';

describe('sum test', () => {
    it('adds 1 + 2 to equal 3', () => {
        expect(1 + 2).toBe(3);
    });
});

好...啦,真的很 Unit test,但是我會想用應該都是想測組件(Component)啊,總不會整個 App 都只有很純的單元測試吧,這樣可靠度感覺不太妙

像是在 Vue 預設還會給你這些:

import { describe, it, expect } from 'vitest'

import { mount } from '@vue/test-utils'
import HelloWorld from '../HelloWorld.vue'

describe('HelloWorld', () => {
  it('renders properly', () => {
    const wrapper = mount(HelloWorld, { props: { msg: 'Hello Vitest' } })
    expect(wrapper.text()).toContain('Hello Vitest')
  })
})

感覺有誠意多了

至少這樣知道怎麼把 Component 掛上去,然後做一些 expect 去測試。


加入 testing-library

之前寫 React 的話可能會對這個測試工具比較熟悉(如果是create-react-app的話),用 Vue3 的就不一定了(因為我覺得 Vue3 提供的 test-utils 就滿好用的了)。

總之 testing-library 也有提供 Svelte,所以可以裝來使用。

$ npm i -D @testing-library/svelte

然後因為我們執行 test 是在 Node 環境,在這個環境下沒有 DOM,所以也需要安裝 jsdom 去模擬。

$npm i -D jsdom

安裝好 jsdom 之後,要記得加入 vite.config.ts 設定。

vite.config.ts

// ...
export default defineConfig({
    // ...
    test: {
        include: ['src/**/*.{test,spec}.{js,ts}'],
        environment: 'jsdom'  // <-- 主要是這行
    }
});

再來就可以去修改 src/index.test.ts:

import { test } from 'vitest';
import { render } from '@testing-library/svelte';
import Page from './routes/+page.svelte';

test('test page', () => {
    const page = render(Page);
    console.log(page);
});

然後執行測試看看有沒有問題

$ npm run test:unit

沒意外會看到 1 passed 且印出一堆可用的函數,就完成了。

如果還是不放心,可以改成下面這一段去測試

test('test page', () => {
    const page = render(Page);
    page.getByText('Welcome to SvelteKit');
});

理論上,如果你的 page.svelte 還是長下面這樣的話,測試就會通過,因為它存在一個元素的文字是 Welcome to SvelteKit

<h1>Welcome to SvelteKit</h1>
<p>Visit <a href="https://kit.svelte.dev">kit.svelte.dev</a> to read the documentation</p>

還是不放心,就把內容改掉,例如

<h1>Welcome to SvelteKit!!</h1>

你馬上就會得到 1 failed 的結果。


其他方便的設定

可以在 vite.config.ts 加入一個 globals 設定,這樣就不用在每一個測試的程式最上面 import {...} from 'vitest'

// ...
export default defineConfig({
    // ...
    test: {
        // ...
        globals: true  // <-- 加入這個
    }
});

這時你的 index.test.ts 就可以拿掉關於 vitestimport 了,如下:

import { render } from '@testing-library/svelte';
import Page from './routes/+page.svelte';

test('test page', () => {
    const page = render(Page);
    page.getByText('Welcome to SvelteKit!!');
});

這時因為你改了設定檔,所以你可能需要重新跑測試的指令,重新跑一次 npm run test:unit 應該一樣會看到正常運作。

但這時又會引發另一個問題(如果你的 lint 正常的話),發現 Cannot find name 'test'. 一長串的錯誤,這時只要去修改 tsconfig.json(如果你使用 TypeScript 的話):

{
    "extends": "./.svelte-kit/tsconfig.json",
    "compilerOptions": {
        // ...
        "types": [
            "vitest/globals"  // <-- 加入這個設定
        ]
    }
}

到這邊就設定完成了。

提醒: 建議還是使用 TypeScript 再使用 globals 設定,至少再我當下測 jsconfig.json 加上 types 設定一樣會噴 is not defined.反正每個檔案上面加一行也沒多麻煩,但也說不定未來哪天就忽然解決了,所以也不一定會碰到這問題。


總結

依照慣例,上面這種重複的事情交給我幫你做就好,可以使用 lai-cmd 幫助你快速設完(就算不成功至少你可以手動貼,不用再花時間查文件)

$ npx lai-cmd@latest init svelte-testing

順便打廣告: 如果你是全新專案想要一次弄好多個環境,也可以只下

$ npx lai-cmd@latest init svelte

他會問你要不要 eslintprettiertailwindcsstesting...等等。




最後更新時間: 2023年04月07日.