日日操夜夜添-日日操影院-日日草夜夜操-日日干干-精品一区二区三区波多野结衣-精品一区二区三区高清免费不卡

公告:魔扣目錄網(wǎng)為廣大站長提供免費(fèi)收錄網(wǎng)站服務(wù),提交前請(qǐng)做好本站友鏈:【 網(wǎng)站目錄:http://www.ylptlb.cn 】, 免友鏈快審服務(wù)(50元/站),

點(diǎn)擊這里在線咨詢客服
新站提交
  • 網(wǎng)站:51998
  • 待審:31
  • 小程序:12
  • 文章:1030137
  • 會(huì)員:747

什么是Vitest?

自從 尤大 的構(gòu)建工具Vite獲得了巨大的人氣,現(xiàn)在有了一個(gè)由它驅(qū)動(dòng)的極快的單元測(cè)試框架。Vitest。

Vitest 與 Jest 兼容,具有開箱即用的 ESM、Typescript 和 JSX 支持,并且由 esbuild 提供支持。它在測(cè)試過程中使用 Vite 開發(fā)服務(wù)器來轉(zhuǎn)換你的文件,并監(jiān)聽你的應(yīng)用程序的相同配置(通過vite.config.js),從而消除了使用Jest等測(cè)試替代品所涉及的重復(fù)工作。

為什么選擇Vitest?

Vite是一個(gè)構(gòu)建工具,旨在為現(xiàn)代 web 項(xiàng)目提供更快、更精簡的開發(fā)體驗(yàn),它開箱即用,支持常見的 web 模式、glob導(dǎo)入和 SSR 等功能。它的許多插件和集成正在促進(jìn)一個(gè)充滿活力的生態(tài)系統(tǒng)。

但這導(dǎo)致了一個(gè)新問題:如何在Vite上編寫單元測(cè)試。

將Jest等框架與Vite一起使用,導(dǎo)致Vite和Jest之間有很多重復(fù)的配置,而 Vitest 解決了這一問題,它消除了為我們的應(yīng)用程序編寫單元測(cè)試所需的額外配置。Vitest 使用與 Vite 相同的配置,并在開發(fā)、構(gòu)建和測(cè)試時(shí)共享一個(gè)共同的轉(zhuǎn)換管道。它還可以使用與 Vite 相同的插件API進(jìn)行擴(kuò)展,并與Jest的API兼容,以方便從Jest遷移,而不需要做很多重構(gòu)工作。

因此,Vitest 的速度也非???。

如何使用 Vitest 來測(cè)試組件

安裝 Vitest

在項(xiàng)目中使用 Vitest 需要 Vite >=v2.7.10 和 Node >=v14 才能工作。

可以使用 npm、yarn 或 pnpm 來安裝 Vitest,根據(jù)自己的喜好,在終端運(yùn)行以下命令:

NPM

npm install -D vitest

YARN

yarn add -D vitest

PNPM

pnpm add -D vitest

 

Vitest 配置

安裝完 Vitest 后,需要將其添加到 vite.config.js 文件中:

vite.config.js

import { defineConfig } from "vite";import vue from "@vitejs/plugin-vue";export default defineConfig({    plugins: [vue()],    //add test to vite config    test: {        // ...    },});

為 TypeScript 配置 Vitest 是類似的,但如果從 Vite 導(dǎo)入 defineConfig,我們需要在配置文件的頂部使用三斜線命令添加對(duì) Vitest 類型的引用。

/// <reference types="vitest" />import { defineConfig } from "vite";import vue from "@vitejs/plugin-vue";// https://vitejs.dev/config/export default defineConfig({    plugins: [vue()],    test: {        // ...    },});

值得注意的是,Vitest 也可以在項(xiàng)目中通過在根文件夾中添加 vitest.config.js 文件來配置。如果這個(gè)文件存在,它將優(yōu)先于 vite.config.js 來配置Vitest。Vitest 也允許額外的配置,可以在配置頁面中找到。

事例演示:Notification

為了看看Vitest的運(yùn)作情況,我們創(chuàng)建一個(gè)顯示三種類型通知的通知組件:info、error 和success。這個(gè)組件的每個(gè)狀態(tài)如下所示:

notification.vue 內(nèi)容如下:

<template>  <div    :class="[      'notification',      type === 'error' ? 'notification--error' : null,      type === 'success' ? 'notification--success' : null,      type === 'info' ? 'notification--info' : null,      message && message.length > 0 ? 'notification--slide' : null,    ]"  >    <img      src="https://res.cloudinary.com/djalafcj9/image/upload/v1634261166/getequityV2/denied_sbmv0e.png"      v-if="type === 'error'"    />    <img      src="https://res.cloudinary.com/djalafcj9/image/upload/v1656690265/getequityV2/Frame_irxz3e.png"      v-if="type === 'success'"    />    <img      src="https://res.cloudinary.com/djalafcj9/image/upload/v1634261166/getequityV2/pending_ctj1ke.png"      v-if="type === 'info'"    />    <p class="notification__text">      {{ message }}    </p>    <button      ref="closeButton"      class="notification__button"      @click="$emit('clear-notification')"    >      <img        src="https://res.cloudinary.com/djalafcj9/image/upload/v1635485821/getequityV2/close_muxdyb.png"      />    </button>  </div></template><script>  export default {    name: "Notification",    emits: ['clear-notification'],    props: {      type: {        type: String,        default: null,      },      message: {        type: String,        default: null,      },    },  };</script><style>  .notification {    transition: all 900ms ease-out;    opacity: 0;    z-index: 300001;    transform: translateY(-100vh);    box-sizing: border-box;    padding: 10px 15px;    width: 100%;    max-width: 730px;    /* margin: 0 auto; */    display: flex;    position: fixed;    /* left: 0; */    top: 20px;    right: 15px;    justify-content: flex-start;    align-items: center;    border-radius: 8px;    min-height: 48px;    box-sizing: border-box;    color: #fff;  }  .notification--slide {    transform: translateY(0px);    opacity: 1;  }  .notification--error {    background-color: #fdecec;  }  .notification__text {    margin: 0;    margin-left: 17px;    margin-right: auto;  }  .notification--error .notification__text {    color: #f03d3e;  }  .notification--success {    background-color: #e1f9f2;  }  .notification--success > .notification__text {    color: #146354;  }  .notification--info {    background-color: #ffb647;  }  .notification__button {    border: 0;    background-color: transparent;  }</style>

在這里,我們使用 message prop創(chuàng)建了一個(gè)顯示動(dòng)態(tài)消息的組件。我們還利用 type prop 來設(shè)計(jì)這個(gè)組件的背景和文本,并利用這個(gè) type prop 顯示我們計(jì)劃的不同圖標(biāo)(error, success, info)。

最后,我們有一個(gè)按鈕,用來通過發(fā)出一個(gè)自定義事件:clear-notification來解除通知。

我們應(yīng)該測(cè)試什么?

現(xiàn)在我們對(duì)需要測(cè)試的組件的結(jié)構(gòu)有了了解,我們可以再思考一下,這個(gè)組件需要做什么,以達(dá)到預(yù)期的功能。

我們的測(cè)試需要檢查以下內(nèi)容:

  • 該組件根據(jù)通知類型渲染出正確的樣式。
  • 當(dāng) message 為空時(shí),通知就會(huì)逐漸消失。
  • 當(dāng)關(guān)閉按鈕被點(diǎn)擊時(shí),該組件會(huì)發(fā)出一個(gè)事件。

為了測(cè)試這些功能,在項(xiàng)目中添加一個(gè) notification.test.js 用于測(cè)試。

安裝測(cè)試依賴項(xiàng)

在編寫單元測(cè)試時(shí),可能會(huì)有這樣的情況:我們需要用一個(gè)什么都不做的假組件來替換組件的現(xiàn)有實(shí)現(xiàn)。這被稱為 **stub(存根)**,為了在測(cè)試中使用存根,我們需要訪問Vue Test Utils的mount方法,這是Vue.js的官方測(cè)試工具庫。

現(xiàn)在我們來安裝Vue Test Utils。

安裝

npm install --save-dev @vue/test-utils@next# oryarn add --dev @vue/test-utils@next

現(xiàn)在,在我們的測(cè)試文件中,我們可以從"@vue/test-utils"導(dǎo)入 mount。

notification.test.js

import { mount } from "@vue/test-utils";

在測(cè)試中,我們還需要能夠模擬 DOM。Vitest目前同時(shí)支持 hAppy-dom 和 jsdom。對(duì)于這個(gè)演示,我們將使用happy-dom,然后安裝它:

yarn add happy-dom --dev

安裝后,我們可以在測(cè)試文件的頂部添加以下注釋...

notification.test.js

/** * @vitest-environment happy-dom */

.或者將此添加到 vite/vitest 配置文件中,以避免在有多個(gè)需要 happy-dom 工作的測(cè)試文件時(shí)出現(xiàn)重復(fù)情況。

vite.config.js

import { defineConfig } from "vite";import vue from "@vitejs/plugin-vue";// https://vitejs.dev/config/export default defineConfig({    plugins: [vue()],    test: {        environment: "happy-dom",    },});

因?yàn)槲覀冎挥幸粋€(gè)測(cè)試文件,所以我們可以選擇第一個(gè)選項(xiàng),所以我們測(cè)試文件內(nèi)容如下:

notification.test.js

/** * @vitest-environment happy-dom */import { mount } from "@vue/test-utils";

有了這些依賴關(guān)系,我們現(xiàn)在可以導(dǎo)入我們要測(cè)試的組件。

notification.test.js

/** * @vitest-environment happy-dom */import { mount } from "@vue/test-utils";import notification from "../components/notification.vue";

常見的Vitest方法

為了編寫測(cè)試,我們需要利用以下常見的方法,這些方法可以從 Vitest 導(dǎo)入。

  • describe:這個(gè)函數(shù)接受一個(gè)名字和一個(gè)函數(shù),用于將相關(guān)的測(cè)試組合在一起。當(dāng)你為一個(gè)有多個(gè)測(cè)試點(diǎn)(如邏輯和外觀)的組件編寫測(cè)試時(shí),它就會(huì)很方便。
  • test/it:這個(gè)函數(shù)代表被測(cè)試的實(shí)際代碼塊。它接受一個(gè)字符串,通常是測(cè)試案例的名稱或描述(例如,渲染成功的正確樣式)和另一個(gè)函數(shù),所有的檢查和測(cè)試在這里進(jìn)行。
  • expect:這個(gè)函數(shù)用于測(cè)試值或創(chuàng)建斷言。它接受一個(gè)預(yù)期為實(shí)際值(字符串、數(shù)字、對(duì)象等)的參數(shù)x,并使用任何支持的方法對(duì)其進(jìn)行評(píng)估(例如toEqual(y),檢查 x 是否與 y 相同)。

因此,我們現(xiàn)在將這些導(dǎo)入我們的測(cè)試文件中

notification.test.js

/** * @vitest-environment happy-dom */import { mount } from "@vue/test-utils";import notification from "../components/notification.vue";import { describe, expect, test } from "vitest";

有了這些函數(shù),我們開始構(gòu)建我們的單元測(cè)試。

建立 Vitest 單元測(cè)試

首先使用 describe 方法將測(cè)試分組。

notification.test.js

describe("notification.vue", () => {    });

在 describe 塊內(nèi),我們添加每個(gè)實(shí)際的測(cè)試。

我們第一個(gè)要測(cè)試的用例是:組件根據(jù)通知類型渲染出正確的樣式。

notification.test.js

describe("notification.vue", () => {    test("renders the correct style for error", () => {    });});

renders the correct style for error 表示 test 所檢查的內(nèi)容的 name。它有助于為代碼塊檢查的內(nèi)容提供上下文,這樣就可以由原作者以外的人輕松維護(hù)和更新。它也使人們?nèi)菀鬃R(shí)別一個(gè)特定的失敗的測(cè)試案例。

 

notification.test.js

describe("notification.vue", () => {    test("renders the correct style for error", () => {       const type = "error";    });});

在我們組件中,定義了一個(gè) type 參數(shù),它接受一個(gè)字符串,用來決定諸如背景顏色、圖標(biāo)類型和文本顏色在組件上的渲染。在這里,我們創(chuàng)建一個(gè)變量 type,并將我們正在處理的類型之一,error (error, info, 或 success)分配給它。

notification.test.js

describe("notification.vue", () => {    test("renders the correct style for error", () => {        const type = "error";        const wrapper = mount(notification, {            props: { type },        });    });});

在這里,我們使用 mount 來存根我們的組件,以便進(jìn)行測(cè)試。

mount 接受組件作為第一個(gè)參數(shù),接受一個(gè)選項(xiàng)列表作為第二個(gè)參數(shù)。這些選項(xiàng)提供了不同的屬性,目的是確保你的組件能在瀏覽器中正常工作。

在這個(gè)列表中,我們只需要 props 屬性。我們使用這個(gè)屬性是因?yàn)槲覀兊?nbsp;notification.vue組件至少需要一個(gè) prop 才能有效工作。

notification.test.js

describe("notification.vue", () => {    test("renders the correct style for error", () => {        const type = "error";        const wrapper = mount(notification, {            props: { type },        });        expect(wrapper.classes()).toEqual(            expect.arrayContaining(["notification--error"])        );    });});

在這一點(diǎn)上,剩下的就是寫一個(gè)斷言,或者更好的是,寫出我們組件的預(yù)期行為,即:renders the correct style for error。

為了做到這一點(diǎn),我們使用了 expect 方法。它接受我們的存根組件和所有的選項(xiàng)(在我們的例子中,我們把它命名為wrapper以方便參考)。

這個(gè)方法可以被鏈接到其他一些方法上,但是對(duì)于這個(gè)特定的斷言,我們要重新檢查組件的類列表是否返回一個(gè)包含這個(gè) notification——error 的數(shù)組。。

我們使用 classes 函數(shù)來實(shí)現(xiàn)這一點(diǎn),該函數(shù)返回包含該組件所有類的數(shù)組。在這之后,下一件事就是使用 toEqual 函數(shù)進(jìn)行比較,它檢查一個(gè)值 X 是否等于** Y**。在這個(gè)函數(shù)中,我們檢查它是否返回一個(gè)包含我們的類的數(shù)組: notification--error。

同樣,對(duì)于 type 為 success 或 info 類型,測(cè)試過程也差不多。

import { mount } from "@vue/test-utils";import notification from "../components/notification.vue";import { describe, expect, test } from "vitest";describe("notification.vue", () => {    test("renders correct style for error", () => {        const type = "error";        const wrapper = mount(notification, {            props: { type },        });        expect(wrapper.classes()).toEqual(            expect.arrayContaining(["notification--error"])        );    });    test("renders correct style for success", () => {        const type = "success";        const wrapper = mount(notification, {            props: { type },        });        expect(wrapper.classes()).toEqual(            expect.arrayContaining(["notification--success"])        );    });    test("renders correct style for info", () => {        const type = "info";        const wrapper = mount(notification, {            props: { type },        });        expect(wrapper.classes()).toEqual(            expect.arrayContaining(["notification--info"])        );    });    test("slides down when message is not empty", () => {        const message = "success";        const wrapper = mount(notification, {            props: { message },        });        expect(wrapper.classes()).toEqual(            expect.arrayContaining(["notification--slide"])        );    });});

到這,我們已經(jīng)寫好了測(cè)試,以確保我們的通知是根據(jù)其類型來進(jìn)行樣式設(shè)計(jì)的。當(dāng)用戶點(diǎn)擊組件上的關(guān)閉按鈕時(shí),我們會(huì)重置 message 參數(shù)。根據(jù)我們的代碼,我們要根據(jù)這個(gè) message 參數(shù)的值來添加或刪除 notification--slide 類,如下所示:

notification.vue

<div    :class="[      'notification',      type === 'error' ? 'notification--error' : null,      type === 'success' ? 'notification--success' : null,      type === 'info' ? 'notification--info' : null,      message && message.length > 0 ? 'notification--slide' : null,    ]"  >//...

如果我們要測(cè)試這個(gè)特定的斷言,它的內(nèi)容如下:

test("slides up when message is empty", () => {        const message = "";        const wrapper = mount(notification, {            props: { message },        });        expect(wrapper.classes("notification--slide")).toBe(false);    });

在這段測(cè)試代碼中,我們用一個(gè)空字符串創(chuàng)建一個(gè) message 變量,并把它作為一個(gè) prop 傳遞給我們的組件。

之后,我們檢查我們組件的類數(shù)組,確保它不包括 notification--slide 類,該類負(fù)責(zé)使我們的組件向下/向外滑動(dòng)到用戶的視圖。為了做到這一點(diǎn),我們使用 toBe 函數(shù),它接收一個(gè)值A,并試圖檢查它是否與 B 相同。

我們還想測(cè)試一下,每當(dāng)組件上的按鈕被點(diǎn)擊,它就會(huì)發(fā)出一個(gè)事件:

test("emits event when close button is clicked", async() => {        const wrapper = mount(notification, {            data() {                return {                    clicked: false,                };            },        });        const closeButton = wrapper.find("button");        await closeButton.trigger("click");        expect(wrapper.emitted()).toHaveProperty("clear-notification");    });

在這個(gè)測(cè)試塊中,我們使用了一個(gè) async 函數(shù),因?yàn)槲覀儗⒂|發(fā)一個(gè)事件,它返回一個(gè) Promise,我們需要等待這個(gè) Promise 的解決,以便捕捉這個(gè)事件所引起的變化。我們還使用了data函數(shù),并添加了一個(gè) clicked 屬性,當(dāng)點(diǎn)擊時(shí)將被切換。

到這,我們需要觸發(fā)這個(gè)點(diǎn)擊事件,我們首先通過使用 find 函數(shù)來獲得按鈕。這個(gè)函數(shù)與querySelector相同,它接受一個(gè)類、一個(gè)id或一個(gè)屬性,并返回一個(gè)元素。

在找到按鈕后,使用 trigger 方法來觸發(fā)一個(gè)點(diǎn)擊事件。這個(gè)方法接受要觸發(fā)的事件名稱(click, focus, blur, keydown等),執(zhí)行這個(gè)事件并返回一個(gè) promise。出于這個(gè)原因,我們等待這個(gè)動(dòng)作,以確保在我們根據(jù)這個(gè)事件做出斷言之前,已經(jīng)對(duì)我們的DOM進(jìn)行了改變。

最后,我們使用返回一個(gè)數(shù)組的 [emitted](
https://test-utils.vuejs.org/api/#emitted) 方法檢查我們的組件所發(fā)出的事件列表。然后我們檢查這個(gè)數(shù)組是否包括 clear-notification 事件。

最后,我們測(cè)試以確保我們的組件渲染出正確的消息,并傳遞給 message prop。

test("renders message when message is not empty", () => {        const message = "Something happened, try again";        const wrapper = mount(notification, {            props: { message },        });        expect(wrapper.find("p").text()).toBe(message);    });

這里,我們創(chuàng)建了一個(gè) message 變量,給它分配了一個(gè)隨機(jī)字符串,并把它作為一個(gè) prop 傳遞給我們的組件。

然后,我們使用 p 標(biāo)簽搜索我們的消息文本,因?yàn)檫@里是顯示消息的地方,并檢查其文本是否與 message 相同。

我們使用 text 方法提取這個(gè)標(biāo)簽的內(nèi)容,這和 innerText很相似。最后,我們使用前面的函數(shù) toBe 來斷言這個(gè)值與 message 相同。

完整的測(cè)試文件

在涵蓋所有這些之后,下面是完整的測(cè)試文件內(nèi)容:

notification.test.js

/** * @vitest-environment happy-dom */import { mount } from "@vue/test-utils";import notification from "../components/notification.vue";import { describe, expect, test } from "vitest";describe("notification.vue", () => {    test("renders the correct style for error", () => {        const type = "error";        const wrapper = mount(notification, {            props: { type },        });        expect(wrapper.classes()).toEqual(            expect.arrayContaining(["notification--error"])        );    });    test("renders the correct style for success", () => {        const type = "success";        const wrapper = mount(notification, {            props: { type },        });        expect(wrapper.classes()).toEqual(            expect.arrayContaining(["notification--success"])        );    });    test("renders the correct style for info", () => {        const type = "info";        const wrapper = mount(notification, {            props: { type },        });        expect(wrapper.classes()).toEqual(            expect.arrayContaining(["notification--info"])        );    });    test("slides down when message is not empty", () => {        const message = "success";        const wrapper = mount(notification, {            props: { message },        });        expect(wrapper.classes()).toEqual(            expect.arrayContaining(["notification--slide"])        );    });    test("slides up when message is empty", () => {        const message = "";        const wrapper = mount(notification, {            props: { message },        });        expect(wrapper.classes("notification--slide")).toBe(false);    });    test("emits event when close button is clicked", async() => {        const wrapper = mount(notification, {            data() {                return {                    clicked: false,                };            },        });        const closeButton = wrapper.find("button");        await closeButton.trigger("click");        expect(wrapper.emitted()).toHaveProperty("clear-notificatioon");    });    test("renders message when message is not empty", () => {        const message = "Something happened, try again";        const wrapper = mount(notification, {            props: { message },        });        expect(wrapper.find("p").text()).toBe(message);    });});

有幾件事需要注意:

  • 我們利用 mount 來存根我們要測(cè)試的組件,它是由Vue Test Utils提供的。(yarn add --dev @vue/test-utils@next)

##運(yùn)行測(cè)試

現(xiàn)在已經(jīng)完成了測(cè)試的編寫,需要運(yùn)行它們。要實(shí)現(xiàn)這一點(diǎn),我們?nèi)?nbsp;package.json,在我們的scripts 部分添加以下幾行。

"scripts": {    "test": "vitest",    "coverage": "vitest run --coverage"},

如果在終端運(yùn)行 yarn vitest 或 yarn test,我們的測(cè)試文件就會(huì)被運(yùn)行,我們應(yīng)該看到測(cè)試結(jié)果和故障。

 

到這,我們已經(jīng)成功地使用Vitest運(yùn)行了我們的第一次測(cè)試。從結(jié)果中需要注意的一點(diǎn)是,由于Vitest的智能和即時(shí)觀察模式,這個(gè)命令只需要運(yùn)行一次,并在我們對(duì)測(cè)試文件進(jìn)行更新和修改時(shí)被重新運(yùn)行。

總結(jié)

使用 Vitest 對(duì)我們的應(yīng)用程序進(jìn)行單元測(cè)試是無縫的,與Jest等替代品相比,需要更少的步驟來啟動(dòng)和運(yùn)行。Vitest 還可以很容易地將現(xiàn)有的測(cè)試從 Jest 遷移到Vitest,而不需要進(jìn)行額外的配置。

作者:Timi Omoyeni 譯者:前端小智 來源:vuemastery 原文:
https://www.vuemastery.com/blog/getting-started-with-vitest

分享到:
標(biāo)簽:Vitest
用戶無頭像

網(wǎng)友整理

注冊(cè)時(shí)間:

網(wǎng)站:5 個(gè)   小程序:0 個(gè)  文章:12 篇

  • 51998

    網(wǎng)站

  • 12

    小程序

  • 1030137

    文章

  • 747

    會(huì)員

趕快注冊(cè)賬號(hào),推廣您的網(wǎng)站吧!
最新入駐小程序

數(shù)獨(dú)大挑戰(zhàn)2018-06-03

數(shù)獨(dú)一種數(shù)學(xué)游戲,玩家需要根據(jù)9

答題星2018-06-03

您可以通過答題星輕松地創(chuàng)建試卷

全階人生考試2018-06-03

各種考試題,題庫,初中,高中,大學(xué)四六

運(yùn)動(dòng)步數(shù)有氧達(dá)人2018-06-03

記錄運(yùn)動(dòng)步數(shù),積累氧氣值。還可偷

每日養(yǎng)生app2018-06-03

每日養(yǎng)生,天天健康

體育訓(xùn)練成績?cè)u(píng)定2018-06-03

通用課目體育訓(xùn)練成績?cè)u(píng)定