日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 前端技术 > vue >内容正文

vue

如何对第一个Vue.js组件进行单元测试

發(fā)布時(shí)間:2023/11/29 vue 28 豆豆
生活随笔 收集整理的這篇文章主要介紹了 如何对第一个Vue.js组件进行单元测试 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

by Sarah Dayan

通過(guò)莎拉·達(dá)揚(yáng)

In Build Your First Vue.js Component we made a star rating component. We’ve covered many fundamental concepts to help you create more complex Vue.js components.

在“ 構(gòu)建您的第一個(gè)Vue.js組件”中,我們制作了星級(jí)評(píng)分組件。 我們介紹了許多基本概念,以幫助您創(chuàng)建更復(fù)雜的Vue.js組件。

Yet, there’s one crucial point you need to build bulletproof components you can use in production: unit testing.

但是,構(gòu)建可在生產(chǎn)中使用的防彈組件的關(guān)鍵一點(diǎn)是: 單元測(cè)試

為什么要對(duì)組件進(jìn)行單元測(cè)試? (Why unit test a component?)

Unit tests are a crucial part of continuous integration. They make your code a lot more reliable by focusing on small, isolated entities and making sure these always behave as expected. You can confidently iterate on your project without fear of breaking things.

單元測(cè)試是持續(xù)集成的關(guān)鍵部分。 通過(guò)專注于小的孤立實(shí)體并確保它們始終表現(xiàn)出預(yù)期的行為,它們使您的代碼更加可靠。 您可以放心地在您的項(xiàng)目上進(jìn)行迭代,而不必?fù)?dān)心會(huì)遇到麻煩。

Unit tests aren’t limited to scripts. Anything we can test in isolation is unit testable, as long as you respect a few good practices. These practices include single-responsibility, predictability, and loose coupling.

單元測(cè)試不僅限于腳本。 只要您尊重一些良好做法,我們可以單獨(dú)測(cè)試的所有內(nèi)容都是可以單元測(cè)試的。 這些實(shí)踐包括單一職責(zé),可預(yù)測(cè)性和松散耦合。

As reusable entities of our app, Vue.js components are great candidates for unit testing. We’ll test the one we made as a single unit with various inputs and user interactions, and make sure it always behaves as we expect.

作為我們應(yīng)用程序的可重用實(shí)體, Vue.js組件非常適合進(jìn)行單元測(cè)試 。 我們將測(cè)試具有多個(gè)輸入和用戶交互的單個(gè)單元,并確保其始終像我們期望的那樣運(yùn)行。

開始之前 (Before we start)

A few things have changed since the initial tutorial. Vue CLI 3 was released. Vue Test Utils — the official Vue.js unit testing utility library — has matured to beta version. In the first tutorial, we used webpack-simple, a prototyping template that doesn’t include testing features. For these reasons, the simplest thing to do is to wipe the slate clean and migrate the project from the tutorial to a more recent Vue.js install.

自從最初的教程以來(lái),發(fā)生了一些變化。 Vue CLI 3已發(fā)布。 Vue Test Utils —官方的Vue.js單元測(cè)試實(shí)用程序庫(kù)—已成熟到beta版。 在第一個(gè)教程中,我們使用了webpack-simple ,這是一個(gè)不包含測(cè)試功能的原型模板。 由于這些原因,最簡(jiǎn)單的方法是清除所有內(nèi)容并將項(xiàng)目從教程遷移到最新的Vue.js安裝。

I re-created the project from the first tutorial so you can download it directly from GitHub. Then, navigate to the unzipped directory and install dependencies.

我從第一個(gè)教程中重新創(chuàng)建了該項(xiàng)目,因此您可以直接從GitHub下載它。 然后,導(dǎo)航到解壓縮目錄并安裝依賴項(xiàng)。

Note: make sure you install Node.js before going further:

注意:在繼續(xù)操作之前, 請(qǐng)確保安裝Node.js :

cd path/to/my/project npm install

Then, run the project:

然后,運(yùn)行項(xiàng)目:

npm run serve

Vue測(cè)試實(shí)用程序和笑話 (Vue Test Utils and Jest)

For this tutorial, we’ll use Vue Test Utils, the official Vue.js testing toolkit, along with Jest, a JavaScript test runner backed by Facebook.

在本教程中,我們將使用Vue Test Utils (官方Vue.js測(cè)試工具包)以及Jest (由Facebook支持JavaScript測(cè)試運(yùn)行程序)一起使用。

Vue Test Utils lets you mount Vue components in isolation and simulate user interactions. It has all the necessary utilities to test single-file components, including those using Vue Router or Vuex.

Vue Test Utils可讓您隔離安裝Vue組件并模擬用戶交互。 它具有測(cè)試單文件組件的所有必需實(shí)用程序,包括使用Vue Router或Vuex的組件。

Jest is a full-featured test runner that requires almost no configuration. It also provides a built-in assertion library.

Jest是功能齊全的測(cè)試運(yùn)行程序,幾乎不需要配置。 它還提供了一個(gè)內(nèi)置的斷言庫(kù)。

Vue CLI 3 (which I used to generate the boilerplate) allows you to pick your favorite test runner, and sets it up for you. If you want to use another test runner (like Mocha), install Vue CLI 3 and generate your own starter project. Then you can migrate the source files from my boilerplate right in it.

Vue CLI 3(我用來(lái)生成樣板 )使您可以選擇自己喜歡的測(cè)試運(yùn)行器,并為您進(jìn)行設(shè)置。 如果要使用其他測(cè)試運(yùn)行程序(例如Mocha ),請(qǐng)安裝Vue CLI 3并生成您自己的啟動(dòng)程序項(xiàng)目。 然后,您可以在其中直接從樣板遷移源文件。

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

A common approach of unit testing is to only focus on the public API (aka black box testing). By overlooking implementation details, you’re allowing internals to change without having to adapt tests. After all, what you want to do is make sure your public API won’t break. What happens under the hood is indirectly tested, but all that matters is for the public API to remain reliable.

單元測(cè)試的常見方法是僅關(guān)注公共API (又名黑盒測(cè)試)。 通過(guò)忽略實(shí)施細(xì)節(jié),您無(wú)需更改測(cè)試即可允許內(nèi)部更改。 畢竟,您要做的就是確保您的公共API不會(huì)損壞 。 幕后發(fā)生的事情經(jīng)過(guò)間接測(cè)試,但重要的是公共API保持可靠。

This is also the official recommendation from the Vue Test Utils guides. Therefore, we’ll only test what we can access from the outside of the component:

這也是Vue Test Utils指南中的官方建議。 因此,我們僅測(cè)試可以從組件外部訪問(wèn)的內(nèi)容:

  • user interactions

    用戶互動(dòng)
  • props changes

    道具變更

We won’t directly test computed properties, methods, or hooks. These will be implicitly tested by testing the public interface.

我們不會(huì)直接測(cè)試計(jì)算的屬性,方法或掛鉤。 這些將通過(guò)測(cè)試公共接口進(jìn)行隱式測(cè)試。

設(shè)置規(guī)格文件 (Setting up a spec file)

Like with regular tests, each component has a spec file which describes all tests we want to run.

與常規(guī)測(cè)試一樣,每個(gè)組件都有一個(gè)規(guī)范文件,該文件描述了我們要運(yùn)行的所有測(cè)試。

Specs are JavaScript files. By convention, they have the same name as the components they’re testing, plus a .spec suffix.

規(guī)范是JavaScript文件。 按照慣例,它們與要測(cè)試的組件同名,并帶有.spec后綴。

Go ahead and create a test/unit/Rating.spec.js file:

繼續(xù)創(chuàng)建一個(gè)test/unit/Rating.spec.js文件:

// Rating.spec.jsimport { shallowMount } from '@vue/test-utils'import Rating from '@/components/Rating'describe('Rating', () => { // your tests go here})

We’ve imported our Rating component and shallowMount. The latter is a Vue Test Utils function which lets us mount our component without mounting its children.

我們已經(jīng)導(dǎo)入了我們的Rating組件和shallowMount 。 后者是Vue Test Utils函數(shù),它使我們可以在不安裝子組件的情況下安裝組件。

The describe function call wraps all the test we’re about to write — it describes our testing suite. It has its own scope, and can itself wrap other nested suites.

describe函數(shù)調(diào)用包裝了我們將要編寫的所有測(cè)試,它描述了我們的測(cè)試套件 。 它具有自己的作用域,并且本身可以包裝其他嵌套套件。

Enough said, let’s start writing tests.

夠了, 讓我們開始編寫測(cè)試

確定測(cè)試方案 (Identifying testing scenarios)

When we look at Rating from the outside, we can see it does the following:

當(dāng)我們從外部查看Rating ,我們可以看到它執(zhí)行以下操作:

  • it renders a list of stars which is equal to the value of the maxStars prop the user passes

    它呈現(xiàn)一個(gè)與用戶通過(guò)的maxStars值相等的星星列表

  • it adds an active class to each star whose index is lower than or equal to the stars prop the user passes

    它為索引小于或等于用戶通過(guò)的stars每個(gè)星星添加一個(gè)active類

  • it toggles the active class on a star when the user clicks it and removes it on the next stars

    當(dāng)用戶單擊某個(gè)active類別時(shí),它將在該active類別上切換,然后在下一個(gè)active類別中將其刪除

  • it toggles the icons star and star-o when the user clicks a star

    當(dāng)用戶單擊星號(hào)時(shí),它將在star和star-o切換

  • it renders a counter if the user sets the hasCounter prop to true, hides it if they set it to false, and displays text saying how many stars of the maximum number of stars are currently active.

    如果用戶將hasCounter prop設(shè)置為true ,則將呈現(xiàn)一個(gè)計(jì)數(shù)器;如果將hasCounter prop設(shè)置為false ,則將隱藏該計(jì)數(shù)器;并顯示文本,說(shuō)明當(dāng)前處于活動(dòng)狀態(tài)的最大星數(shù)中的幾顆。

Notice we’re only looking at what the component does from the outside. We don’t care that clicking a star executes the rate method, or that the internal stars data property changes. We could rename these, but this shouldn’t break our tests.

注意,我們只是從外部查看組件的功能。 我們不在乎單擊星標(biāo)執(zhí)行rate方法,還是在內(nèi)部stars數(shù)據(jù)屬性更改。 我們可以重命名它們,但這不會(huì)破壞我們的測(cè)試。

我們的第一個(gè)測(cè)試 (Our first test)

Let’s write our first test. We first need to manually mount our component with shallowMount, and store it in a variable on which we’ll perform assertions. We can also pass props through the propsData attribute, as an object.

讓我們寫我們的第一個(gè)測(cè)試。 首先,我們需要使用shallowMount手動(dòng)安裝組件,并將其存儲(chǔ)在將要執(zhí)行斷言的變量中。 我們還可以將props作為對(duì)象通過(guò)propsData屬性傳遞。

The mounted component is an object which comes with a handful of useful utility methods:

掛載的組件是一個(gè)對(duì)象,帶有一些有用的實(shí)用程序方法:

describe('Rating', () => { const wrapper = shallowMount(Rating, { propsData: { maxStars: 6, grade: 3 } }) it('renders a list of stars with class `active` equal to prop.grade', () => { // our assertion goes here })})

Then, we can write our first assertion:

然后,我們可以編寫第一個(gè)斷言:

it('renders a list of stars with class `active` equal to prop.grade', () => { expect(wrapper.findAll('.active').length).toEqual(3)})

Let’s analyze what’s happening here. First, we’re using Jest’s expect function, which takes the value we want to test as an argument. In our case, we call the findAll method on our wrapper to fetch all elements with an active class. This returns a WrapperArray, which is an object that contains an array of Wrappers.

讓我們分析一下這里發(fā)生的事情。 首先,我們使用玩笑的expect功能,這需要我們想要的值來(lái)測(cè)試作為參數(shù)。 在我們的例子中,我們?cè)趙rapper上調(diào)用findAll方法來(lái)獲取具有active類的所有元素。 這將返回WrapperArray ,該對(duì)象是包含Wrappers數(shù)組的對(duì)象。

A WrapperArray has two properties: wrappers (the contained Wrappers) and length (the number of Wrappers). The latter is what we need to have the expected number of stars.

甲WrapperArray具有兩個(gè)屬性: wrappers (所包含的Wrappers )和length (的數(shù)量Wrappers )。 后者是我們需要具有預(yù)期星數(shù)的東西。

The expect function also returns an object on which we can call methods to test the passed value. These methods are called matchers. Here, we use the toEqual matcher and pass it the expected value as in arguments. The method returns a boolean, which is what a test expects to either pass or fail.

expect函數(shù)還返回一個(gè)對(duì)象,我們可以在該對(duì)象上調(diào)用方法以測(cè)試傳遞的值。 這些方法稱為匹配器 。 在這里,我們使用toEqual匹配器并將期望的值傳遞給參數(shù)。 該方法返回一個(gè)布爾值,這是測(cè)試期望通過(guò)或失敗的布爾值。

To summarize, here we say we expect the total amount of elements with the class active we find in our wrapper to be equal to 3 (the value we assigned to the grade prop).

總而言之,在這里我們說(shuō)我們期望在包裝器中找到的active類的元素總數(shù)等于3(我們?yōu)間rade道具分配的值)。

In your terminal, run your test:

在終端中,運(yùn)行測(cè)試:

npm run test:unit

You should see it pass ?

您應(yīng)該看到它通過(guò)嗎?

Time to write some more.

是時(shí)候?qū)懜嗔恕?

模擬用戶輸入 (Simulating user input)

Vue Test Utils makes it easy to simulate what real users end up doing in production. In our case, users can click on stars to toggle them. We can fake this in our tests with the trigger method, and dispatch all kinds of events.

Vue Test Utils使模擬真實(shí)用戶最終在生產(chǎn)中所做的工作變得容易。 在我們的情況下,用戶可以單擊星號(hào)來(lái)切換它們。 我們可以使用trigger方法在測(cè)試中進(jìn)行偽造,并調(diào)度各種事件。

it('adds `active` class on an inactive star when the user clicks it', () => { const fourthStar = wrapper.findAll('.star').at(3) fourthStar.trigger('click') expect(fourthStar.classes()).toContain('active')})

Here, we first get our fourth star with findAll and at, which returns a Wrapper from a WrapperArray at the passed index (zero-based numbering). Then, we simulate the click event on it — we’re mimicking the action from a user who would click or tap the fourth star.

在這里,我們首先使用findAll和at獲得第四顆星,它從WrapperArray返回傳入的索引(從零開始的編號(hào))處的Wrapper 。 然后,我們模擬其上的click事件-我們模仿的是單擊或輕擊第四顆星星的用戶的操作。

Since we set the grade prop to 3, the fourth star should be inactive before we click, therefore the click event should make it active. In our code, this is represented by a class active which we append on stars only when they’re activated. We test it by calling the classes method on the star, which returns its class names as an array of strings. Then, we use the toContain matcher to make sure the active class is here.

由于我們將grade prop設(shè)置為3,因此在單擊之前第四顆星星應(yīng)該處于非活動(dòng)狀態(tài),因此單擊事件應(yīng)使其處于活動(dòng)狀態(tài)。 在我們的代碼中,這由active類表示,僅當(dāng)激活它們時(shí),我們才將它們附加在星星上。 我們通過(guò)在星號(hào)上調(diào)用classes方法來(lái)對(duì)其進(jìn)行測(cè)試,該方法將其類名稱作為字符串?dāng)?shù)組返回。 然后,我們使用toContain匹配器確保active類在此處。

設(shè)置和拆卸 (Setup and teardown)

Since we’ve triggered a click on our component, we’ve mutated its state. The problem is that we’re using that same component for all our tests. What happens if we change the order of our tests, and move this one to first position? Then the second test would fail.

由于我們觸發(fā)了組件的點(diǎn)擊,因此我們改變了它的狀態(tài)。 問(wèn)題是我們?cè)谒袦y(cè)試中都使用了相同的組件。 如果我們更改測(cè)試順序并將其移至第一位會(huì)發(fā)生什么? 然后第二次測(cè)試將失敗。

You don’t want to rely on brittle things like order when it comes to tests. A test suite should be robust, and existing tests should ideally not change unless you’re breaking the API.

在測(cè)試中,您不想依賴諸如訂單之類的易碎物品。 測(cè)試套件應(yīng)該很健壯,并且理想情況下,除非破壞API,否則現(xiàn)有測(cè)試不應(yīng)更改。

We want to make sure we always have a predictable wrapper to perform assertions on. We can achieve this with setup and teardown functions. These are helpers which let us initialize things before we run tests, and clean up afterward.

我們要確保始終有一個(gè)可預(yù)測(cè)的包裝器來(lái)執(zhí)行斷言。 我們可以通過(guò)設(shè)置和拆卸功能來(lái)實(shí)現(xiàn)。 這些幫助程序使我們可以在運(yùn)行測(cè)試之前初始化事情,然后進(jìn)行清理。

In our case, a way of doing it could be to create our wrapper before each test and destroy it afterwards.

在我們的情況下,一種方法是在每次測(cè)試之前創(chuàng)建包裝,然后再銷毀它。

let wrapper = nullbeforeEach(() => { wrapper = shallowMount(Rating, { propsData: { maxStars: 6, grade: 3 } })})afterEach(() => { wrapper.destroy()})describe('Rating', () => { // we remove the `const wrapper = …` expression // …}

As their names suggest, beforeEach and afterEach run before and after each test, respectively. This way we can be 100% sure we’re using a fresh wrapper whenever we run a new test.

顧名思義, beforeEach和afterEach分別在每個(gè)測(cè)試之前和之后運(yùn)行。 這樣,我們可以在每次運(yùn)行新測(cè)試時(shí)100%確保使用新包裝。

測(cè)試的特殊標(biāo)識(shí)符 (Special identifiers for tests)

It’s never a good idea to mix selectors for styling and other purposes, such as test hooks.

混合使用選擇器以進(jìn)行樣式設(shè)計(jì)和其他用途(例如測(cè)試掛鉤)絕不是一個(gè)好主意。

What if you change the tag name or the class?

如果更改標(biāo)簽名稱或類怎么辦?

What if you don’t have a specific identifier on an element you want to test such as, in our case, the counter?

如果在要測(cè)試的元素(例如我們的計(jì)數(shù)器)上沒(méi)有特定的標(biāo)識(shí)符怎么辦?

You don’t want to pollute your production code with classes which would be useless there. It would be much better to have dedicated hooks for tests, such as a dedicated data attribute, but only during tests. This way a mess isn’t left in the final build.

您不想用在那里沒(méi)有用的類來(lái)污染您??的生產(chǎn)代碼。 最好有專用的鉤子來(lái)進(jìn)行測(cè)試,例如專用的數(shù)據(jù)屬性, 但只在測(cè)試期間進(jìn)行 。 這樣一來(lái),就不會(huì)在最終版本中留下混亂。

One way to handle this is to create a custom Vue directive.

一種解決方法是創(chuàng)建自定義Vue指令 。

The Vue instance has a directive method which takes two arguments — a name, and an object of functions for each hook of the component lifecycle when injected in the DOM. You can also pass a single function if you don’t care about a specific hook.

Vue實(shí)例具有一個(gè)directive方法,該方法帶有兩個(gè)參數(shù)- 名稱 ,和注入到DOM 中的組件生命周期的每個(gè)掛鉤的 函數(shù)對(duì)象 。 如果您不關(guān)心特定的鉤子,也可以傳遞一個(gè)函數(shù)。

Let’s create a new directory called directives in src/, and add a test.js file. We’ll export the function we want to pass in our directive.

讓我們?cè)趕rc/創(chuàng)建一個(gè)名為directives的新目錄,并添加一個(gè)test.js文件。 我們將導(dǎo)出要傳遞給指令的函數(shù)。

// test.jsexport default (el, binding) => { // do stuff}

A directive hook can take several arguments and, in our case, we only need the first two: el and binding. The el argument refers to the element the directive is bound to. The binding argument is an object which contains the data we passed in the directive. This way we can manipulate the element as we like.

指令掛鉤可以帶有多個(gè)參數(shù) ,在我們的例子中,我們僅需要前兩個(gè)參數(shù): el和binding 。 el參數(shù)是指指令綁定到的元素。 binding參數(shù)是一個(gè)對(duì)象,其中包含我們?cè)谥噶钪袀鬟f的數(shù)據(jù)。 這樣,我們可以根據(jù)需要操縱元素。

export default (el, binding) => { Object.keys(binding.value).forEach(value => { el.setAttribute(`data-test-${value}`, binding.value[value]) })}

We’re passing an object to our directive, so we can generate data attributes starting with data-test-. In the handler function, we iterate over each property of binding, and we set a data attribute — based on the name and value — on our element.

我們將一個(gè)對(duì)象傳遞給指令,因此我們可以生成以data-test-開頭的數(shù)據(jù)屬性。 在處理程序函數(shù)中,我們迭代binding每個(gè)屬性,并在元素上設(shè)置一個(gè)基于名稱和值的data屬性。

Now we need to register our directive so we can use it. We can do it globally but, in our case, we’re only going to register it locally — right in our Rating.vue component.

現(xiàn)在我們需要注冊(cè)指令,以便可以使用它。 我們可以在全球范圍內(nèi)進(jìn)行操作,但就我們而言,我們只打算在本地進(jìn)行注冊(cè)-就在我們的Rating.vue組件中。

<script>import Test from '@/directives/test.js'export default { // … directives: { Test }, // …}</script>

Our directive is now accessible under the v-test name. Try setting the following directive on the counter:

現(xiàn)在可以使用v-test名稱訪問(wèn)我們的指令。 嘗試在柜臺(tái)上設(shè)置以下指令:

<span v-test="{ id: 'counter' }" v-if="hasCounter"> {{ stars }} of {{ maxStars }}</span>

Now inspect the HTML in your browser with the developer tools. Your counter should look like this:

現(xiàn)在,使用開發(fā)人員工具在瀏覽器中檢查HTML。 您的柜臺(tái)應(yīng)如下所示:

<span data-test-id="counter">2 of 5</span>

Great, it works! Now, we don’t need this either in dev mode nor when we build the project. The sole purpose of this data attribute is to be able to target elements during tests, so we only want to set it up when we run them. For this, we can use the NODE_ENV environment variable provided by Webpack, the module bundler powering our project.

太好了! 現(xiàn)在,無(wú)論是在開發(fā)模式下還是在構(gòu)建項(xiàng)目時(shí),我們都不需要它。 此數(shù)據(jù)屬性的唯一目的是能夠在測(cè)試期間定位元素,因此我們只想在運(yùn)行它們時(shí)進(jìn)行設(shè)置。 為此,我們可以使用NODE_ENV提供的NODE_ENV環(huán)境變量,該模塊是為我們的項(xiàng)目提供動(dòng)力的模塊捆綁器。

When we run tests, NODE_ENV is set to 'test'. Therefore, we can use it to determine when to set the test attributes or not.

當(dāng)我們運(yùn)行測(cè)試時(shí), NODE_ENV設(shè)置為'test' 。 因此,我們可以使用它來(lái)確定何時(shí)設(shè)置測(cè)試屬性。

export default (el, binding) => { if (process.env.NODE_ENV === 'test') { Object.keys(binding.value).forEach(value => { el.setAttribute(`data-test-${value}`, binding.value[value]) }) }}

Refresh your app in the browser and inspect the counter again: the data attribute is gone.

在瀏覽器中刷新您的應(yīng)用,然后再次檢查計(jì)數(shù)器: data屬性消失了

Now we can use the v-test directive for all elements we need to target. Let’s take our test from earlier:

現(xiàn)在,我們可以對(duì)需要定位的所有元素使用v-test指令。 讓我們從前面進(jìn)行測(cè)試:

it('adds `active` class on an inactive star when the user clicks it', () => { const fourthStar = wrapper.findAll('[data-test-id="star"]').at(3) fourthStar.trigger('click') expect(fourthStar.classes()).toContain('active')})

We’ve replaced the .star selector with [data-test-id="star"], which allows us to change classes for presentation purposes without breaking tests. We get one of the benefits of the single-responsibility principle and loose coupling — when your abstractions only have a single reason to change, you avoid all kinds of pesky side-effects.

我們將.star選擇器替換為[data-test-id="star"] ,這使我們可以為演示目的而更改類而不會(huì)破壞測(cè)試。 我們得到的好處之一單一職責(zé)原則和松散的耦合 -當(dāng)你的抽象只有一個(gè)理由去改變,你避免各種討厭的副作用。

我們還應(yīng)該在測(cè)試的類中使用這些鉤子嗎? (Should we also use these hooks for the classes we test?)

After setting this directive to target elements to test, you may be wondering if you should also use them to replace the classes we actively look for. Let’s look at the assertion from our first test:

在將此指令設(shè)置為要測(cè)試的目標(biāo)元素之后,您可能想知道是否還應(yīng)該使用它們來(lái)代替我們積極尋找的類。 讓我們看一下第一個(gè)測(cè)試的斷言:

expect(wrapper.findAll('.active').length).toEqual(3)

Should we use v-test on the elements with the active class, and replace the selector in the assertion? Great question.

我們是否應(yīng)該在active類的元素上使用v-test ,并在斷言中替換選擇器? 好問(wèn)題

Unit tests are all about testing one thing at a time. The first argument of the it function is a string, with which we describe what we’re doing from a consumer perspective.

單元測(cè)試都是一次測(cè)試一件事。 it函數(shù)的第一個(gè)參數(shù)是一個(gè)字符串,我們從消費(fèi)者的角度描述我們?cè)谧鍪裁础?

The test that wraps our assertion says renders a list of stars with class active equal to prop.grade. This is what the consumer expects. When they pass a number to the grade property, they expect to retrieve an equal number of active or selected stars. Yet, in our component’s logic, the active class is precisely what we use to define this trait. We assign it depending on a specific condition, so we can visually differentiate active stars from the others. Here, the presence of this specific class is exactly what we want to test.

包含斷言的測(cè)試將renders a list of stars with class active equal to prop.grade. 這就是消費(fèi)者的期望。 當(dāng)他們將數(shù)字傳遞給grade屬性時(shí),他們希望檢索到相等數(shù)量的活動(dòng)或選定的恒星。 但是,按照組件的邏輯, active類正是我們用來(lái)定義此特征的類。 我們根據(jù)特定條件對(duì)其進(jìn)行分配,因此我們可以在視覺(jué)上區(qū)分活躍恒星和其他恒星。 在這里,這個(gè)特定類的存在正是我們要測(cè)試的。

So, when deciding whether you should use a selector you already have or set a v-test directive, ask yourself the question: what am I testing, and does using this selector makes sense for a business logic perspective?

因此,在決定是否應(yīng)該使用已有的選擇器或設(shè)置v-test指令時(shí),請(qǐng)問(wèn)自己一個(gè)問(wèn)題: 我正在測(cè)試什么,并且從業(yè)務(wù)邏輯角度來(lái)看,使用此選擇器是否有意義?

它與功能或端到端測(cè)試有何不同? (How is it different from functional or end-to-end tests?)

At first, it might look odd to unit test components. Why would you unit test UI and user interactions? Isn’t that what functional tests are here for?

首先,對(duì)于單元測(cè)試組件而言,它看起來(lái)很奇怪。 為什么要對(duì)UI和用戶交互進(jìn)行單元測(cè)試? 這不是功能測(cè)試嗎?

There is a fundamental yet subtle difference to make between testing a component’s public API — aka from a consumer perspective — and testing a component from a user perspective. First, let’s underline something important: we’re testing well-defined JavaScript functions, not pieces of UI.

消費(fèi)者的角度測(cè)試組件的公共API(從用戶角度來(lái)看)與從用戶的角度測(cè)試組件之間存在根本但微妙的區(qū)別。 首先,讓我們強(qiáng)調(diào)一些重要的事情: 我們正在測(cè)試定義明確JavaScript函數(shù),而不是UI部分

When you look at a single-file component it’s easy to forget the component compiles into a JavaScript function. We’re not testing the underlying Vue mechanism which, from this function, causes UI-oriented side-effects like injecting HTML in the DOM. That’s what Vue’s own tests already take care of. In our case, our component is no different from any other function: it accepts input and returns an output. These causes and consequences are what we’re testing, and nothing else.

當(dāng)您查看單個(gè)文件組件時(shí),很容易忘記該組件會(huì)編譯為JavaScript函數(shù)。 我們沒(méi)有測(cè)試底層的Vue機(jī)制,該機(jī)制會(huì)從此函數(shù)引起面向UI的副作用,例如在DOM中注入HTML。 這就是Vue自己的測(cè)試已經(jīng)解決的問(wèn)題。 在我們的例子中,我們的組件與其他函數(shù)沒(méi)有什么不同: 它接受輸入并返回輸出 。 這些因果關(guān)系是我們正在測(cè)試的,僅此而已。

What’s confusing is that our tests look a bit different from regular unit tests. Usually, we write things like:

令人困惑的是我們的測(cè)試看起來(lái)與常規(guī)單元測(cè)試有些不同。 通常,我們這樣寫:

expect(add(3)(4)).toEqual(7)

There’s no debate here. Input and output of data, that’s all we care about. With components, we’re expecting things to render visually. We’re traversing a virtual DOM and testing for the presence of nodes. That’s also what you do with functional or end-to-end tests, with tools like Selenium or Cypress.io. So how does that differ?

這里沒(méi)有辯論。 數(shù)據(jù)的輸入和輸出,這就是我們關(guān)心的全部。 對(duì)于組件,我們期望事物能夠以可視方式呈現(xiàn)。 我們正在遍歷虛擬DOM并測(cè)試節(jié)點(diǎn)的存在。 您也可以使用Selenium或Cypress.io之類的工具來(lái)進(jìn)行功能或端到端測(cè)試。 那有什么不同呢?

You need not to confuse what we’re doing to fetch the data we want to test and the actual purpose of the test. With unit tests, we’re testing isolated behaviors. With functional or end-to-end tests, we’re testing scenarios.

你不必混淆我們正在做的事情來(lái)獲取我們想要的測(cè)試和試驗(yàn)的實(shí)際目的的數(shù)據(jù)。 通過(guò)單元測(cè)試,我們正在測(cè)試孤立的行為。 通過(guò)功能測(cè)試或端到端測(cè)試,我們正在測(cè)試場(chǎng)景

A unit test makes sure a unit of the program behaves as expected. It’s addressed to the consumer of the component — the programmer who uses the component in their software. A functional test ensures a feature or a workflow behaves as expected, from a user perspective — the final user, who consumes the full software.

單元測(cè)試可確保程序的單元行為符合預(yù)期。 它面向的是組件的使用者 -在其軟件中使用該組件的程序員。 從用戶的角度(即使用完整軟件的最終用戶)的角度出發(fā),功能測(cè)試可確保功能工作流程的行為符合預(yù)期。

更進(jìn)一步 (Going further)

I won’t go into the detail of each test, because they all share a similar structure. You can find the full spec file on GitHub, and I strongly recommend you try to implement them yourself first. Software testing is an art as much as it is a science, and requires twice as much practice as it requires theory.

我不會(huì)詳細(xì)介紹每個(gè)測(cè)試,因?yàn)樗鼈兌季哂邢嗨频慕Y(jié)構(gòu)。 您可以在GitHub上找到完整的規(guī)范文件 ,我強(qiáng)烈建議您嘗試首先自己實(shí)現(xiàn)它們。 軟件測(cè)試既是一門科學(xué),又是一門科學(xué),它需要的實(shí)踐是理論的兩倍。

Don’t worry if you didn’t get everything, or if you struggle with writing your first tests: testing is notoriously hard. Also, if you have a question, don’t hesitate to hit me up on Twitter!

如果您一無(wú)所獲,也不必?fù)?dān)心編寫第一個(gè)測(cè)試的麻煩: 眾所周知,測(cè)試很難 。 另外,如果您有任何疑問(wèn),請(qǐng)隨時(shí)在Twitter上與我聯(lián)系!

Originally published at frontstuff.io.

最初發(fā)布在frontstuff.io上 。

翻譯自: https://www.freecodecamp.org/news/how-to-unit-test-your-first-vue-js-component-14db6e1e360d/

總結(jié)

以上是生活随笔為你收集整理的如何对第一个Vue.js组件进行单元测试的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。