Redian新闻
>
如何使用Vue测试库测试应用程序?

如何使用Vue测试库测试应用程序?

科技


新钛云服已累计为您分享714篇技术干货


摘要

Vue测试库可以帮助您通过模拟用户与APP之间的交互方式来测试您的应用程序


在本文中,我们将使用Vue测试库来测试Vue应用程序,这是一个轻量级的库,它强调从用户的角度来测试您的前端应代码


阅读前应该具备:

· 了解vue相关知识

· 熟悉测试APP的UI

按照惯例,在Vue的生态中,当您要测试应用程序时,您可以使用@ vue/test-utils-Vue的官方测试库。这个库提供相关API以方便用户测试渲染的Vue组件实例。例如:
// example.spec.js
import { shallowMount } from '@vue/test-utils'
import HelloWorld from '@/components/HelloWorld.vue'

describe('HelloWorld.vue', () => {
  it('renders props.msg when passed', () => {
    const msg = 'new message'
    const wrapper = shallowMount(HelloWorld, {
      propsData: { msg }
    })
    expect(wrapper.text()).toMatch(msg)
  })
})

您可以看到我们正在使用@vue/test-utils库提供的shallowMount函数来载入渲染我们项目开发代码中Vue组件。
上述测试Vue组件的方法的问题在于,用户最终要与DOM进行交互,对于Vue如何渲染UI没有任何了解。相反,一般只会通过文本内容、输入框的标签以及页面上的一些其他可见的视觉线索来寻找对应UI元素是否可见。
一个更好的方法是为你的Vue应用程序编写测试用例,以反映实际用户如何与之交互,例如在结账页面中寻找一个增加产品购买数量的按钮,所以才需要Vue测试库。

Vue测试库是什么?

Vue测试库是Vue的一个轻量级测试库,它在@vue/test-utils的基础上提供了轻量级的实用功能。它是根据一个简单的引导原则创建的:
The more your tests resemble the way your software is used, the more confidence they can give you.
— testing-library.com

为什么使用Vue测试库?

· 你要写的测试用例不需要关注于实现细节,即测试方法的实现方式,而不是它是否产生了所需要的结果。


· 您想编写针对实际DOM节点而不是渲染的Vue组件的测试。


· 您想要编写以与用户相同的方式查询DOM的测试。


Vue测试库的原理

Vue测试库通过提供用于查询DOM的功能来发挥作用,就像用户与DOM进行交互的方式一样。这些实用的功能使您可以通过标签文本查找元素,从其文本内容中找到链接和按钮,并断言可以完全访问Vue应用程序。对于无法通过文字内容或标签来查找元素或其它不切实际的情况,Vue测试库提供了一种比较推荐的方法,即通过使用data-testid属性作为标记来查找这些元素。
data- testd属性被添加到您计划在测试中查询的HTML元素中。如
<button data-testid="checkoutButton">Check Out</button>

开始使用Vue测试库

现在,你已经了解了为什么应该使用Vue测试库以及其工作方式,让我们在全新的Vue CLI创建的Vue项目中进行配置。
首先,我们将通过在终端中运行下面的命令创建一个新项目(假设您的机器上安装了Vue CLI)
vue create vue-testing-library-demo
为了运行测试,我们将使用Jest,它是Facebook开发的测试运行程序。Vue CLI具有一个可以轻松配置Jest的插件。让我们添加该插件:
vue add unit-jest
添加完成后,您会发现在package.json中添加了一个新脚本:
 "test:unit""vue-cli-service test:unit",
这个脚本就是用来运行测试用例的。它还在src中添加了一个新的tests文件夹,并在tests文件夹中添加了一个单元文件夹,其中包含一个名为example.spec.js的示例测试文件。基于Jest的配置,当我们运行npm run test:unit时,Jest将在tests目录中查找文件并运行测试文件。让我们运行示例测试文件:
npm run test:unit
这应该会运行test/unit目录下的example.spec.js测试文件。让我们看看这个文件的内容。
import { shallowMount } from '@vue/test-utils'
import HelloWorld from '@/components/HelloWorld.vue'

describe('HelloWorld.vue', () => {
  it('renders props.msg when passed', () => {
    const msg = 'new message'
    const wrapper = shallowMount(HelloWorld, {
      propsData: { msg }
    })
    expect(wrapper.text()).toMatch(msg)
  })
})
默认情况下,使用Vue CLI插件安装Jest会安装@vue/test-utils,因此上面的测试文件使用的是@vue/test-utils中的showMount函数。但是我们要使用Vue测试库而不是@vue/test-utils。为此,我们将卸载@vue/test-utils,因为我们将不需要它。
npm uninstall @vue/test-utils --save-dev
然后,我们安装Vue测试库
npm install @testing-library/vue --save-dev
接着,我们将tests/unit/example.spec.js修改为:
import { render } from '@testing-library/vue'
import HelloWorld from '@/components/HelloWorld.vue'

describe('HelloWorld.vue', () => {
  it('renders props.msg when passed', () => {
    const msg = 'new message'
    const { getByText } = render(HelloWorld, {
      props: { msg }
    })
    getByText(msg)
  })
})
再次运行测试,应该可以通过。让我们看看我们做了什么:

· 我们使用Vue Testing Library公开的render函数来渲染HelloWorld组件。render是渲染Vue组件的唯一方法。调用render时,需要传入Vue组件和一个可选的options对象。


· 然后,我们使用options对象传递HelloWorld组件所需的参数。render将返回一个带有辅助方法的对象来查询DOM,而这些方法之一就是getByText。


· 最后,我们使用getByText断言DOM中是否存在具有“新消息”文本内容的元素。


到目前为止,您可能已经注意到从考虑测试渲染的Vue组件到用户在DOM中看到的转变。这一转变将使您从用户的角度测试应用程序,而不是将重点放在实现细节上。

我们的演示应用

现在,我们已经确定了如何使用Vue测试库在Vue中完成测试,我们将继续测试演示应用程序。但是首先,我们将充实应用程序的UI。我们的演示应用程序是一个产品的简单结帐页面。我们将测试用户是否可以在结帐前增加产品的数量,他/她是否可以看到产品名称和价格,等等。让我们开始吧。
首先,在components /目录中创建一个名为checkout的新Vue组件,并将以下代码段添加到其中:
<template>
<div class="checkout">
<h1>{{ product.name }} - <span data-testid="finalPrice">${{ product.price }}</span></h1>
<div class="quantity-wrapper">
<div>
<label for="quanity">Quantity</label>
<input type="number" v-model="quantity" name="quantity" class="quantity-input" />
</div>
<div>
<button @click="incrementQuantity" class="quantity-btn">+</button>
<button @click="decrementQuantity" class="quantity-btn">-</button>
</div>
</div>
<p>final price - $<span data-testId="finalPrice">{{ finalPrice }}</span></p>
<button @click="checkout" class="checkout-btn">Checkout</button>
</div>
</template>
<script>
export default {
data() {
return {
quantity: 1,
}
},
props: {
product: {
required: true
}
},
computed: {
finalPrice() {
return this.product.price * this.quantity
}
},
methods: {
incrementQuantity() {
this.quantity++;
},
decrementQuantity() {
if (this.quantity == 1) return;
this.quantity--;
},
checkout() {

}
}
}
</script>

<style scoped>
.quantity-wrapper {
margin: 2em auto;
width: 50%;
display: flex;
justify-content: center;
}

.quantity-wrapper div {
margin-right: 2em;
}
.quantity-input {
margin-left: 0.5em;
}
.quantity-wrapper button {
margin-right: 1em;
}
button {
cursor: pointer;
}
</style>

再将App.vue改成:
<template>
<div id="app">
<check-out :product="product" />
</div>
</template>

<script>
import CheckOut from './components/CheckOut.vue'

export default {
name: 'App',
data() {
return {
product: {
name: 'Shure Mic SM7B',
price: 200,
}
}
},
components: {
CheckOut
}
}
</script>

<style>
#app {
font-family: Avenir, Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-align: center;
color: #2c3e50;
margin-top: 60px;
}
</style>

对于我们的测试用例,我们将测试以下场景:

· 用户可以看到产品名称吗?

· 用户能看到产品价格吗?

· 用户能否增加产品数量?

· 用户可以减少产品数量吗?

· 用户可以随着数量的变化实时查看更新的总价吗?

我们的UI界面是非常简约,因为重点在于如何使用Vue测试库进行测试。让我们继续测试Checkout组件。在tests / unit /中创建一个名为checkout.spec.js的新测试文件内容如下:
import { render, fireEvent } from '@testing-library/vue'
import CheckOut from '@/components/CheckOut.vue'

const product = {
    name: 'Korg Kronos',
    price: 1200
}
describe('Checkout.vue', () => {
  // tests goes here
})
我们的第一个测试用例将是检查产品名称是否正常显示。我们将这样做:
 it('renders product name', () => {
        const { getByText } = render(CheckOut, {
            props: { product }
        })

        getByText(product.name)
 })
然后,我们将检查产品价格是否正常显示:
it('renders product price', () => {
        const { getByText } = render(CheckOut, {
            props: { product }
        })

        getByText("$" + product.price)
 })
继续测试Checkout组件,我们将使用getByDisplayValue helper方法测试用户看到的初始数量是否为1:
it('renders initial quantity as 1', () => {
        const { getByDisplayValue, getByText } = render(CheckOut, {
            props: { product }
        })
        getByDisplayValue(1)
    })
接下来,我们将检查当用户点击增加产品数量的按钮时,是否增加了产品数量。为此,我们将使用Vue测试库中的fireEvent实用程序触发单击事件。下面是完整的实现
it('increments product quantity', async () => {
        const { getByDisplayValue, getByText } = render(CheckOut, {
            props: { product }
        })
        const incrementQuantityButton = getByText('+')
        await fireEvent.click(incrementQuantityButton)
        getByDisplayValue(2)
})
当数量为1时,我们将做同样的递减操作-在这种情况下,我们不减少数量。
当数量为2时,让我们编写两个测试用例。
it('does not decrement quantity when quanty is 1'async () => {
        const { getByDisplayValue, getByText } = render(CheckOut, {
            props: { product }
        })
        const decrementQuantityButton = getByText('-')
        await fireEvent.click(decrementQuantityButton)
        getByDisplayValue(1)
    })

 it('decrement quantity when quantity greater than 1'async () => {
        const { getByDisplayValue, getByText } = render(CheckOut, {
            props: { product }
        })
        const incrementQuantityButton = getByText('+')
        const decrementQuantityButton = getByText('-')
        await fireEvent.click(incrementQuantityButton)
        await fireEvent.click(decrementQuantityButton)
        getByDisplayValue(1)
    })
最后,我们将测试是否可以点击数量增减来查看最终价格是否正常显示给用户。
在整个测试案例中,您会注意到,我们更加专注于从用户肉眼能看到并与之交互的角度编写测试。以这种方式编写测试可以确保我们测试的是对应用的用户比较重要的东西。

总结

本文介绍的于测试Vue应用程序的库和方法,称为Vue测试库,我们将了解如何设置它以及如何使用它编写Vue组件的测试用例。
您可以在GitHub上找到演示项目  https://github.com/DominusKelvin/vue-testing-library-demo

*原文链接: https://www.smashingmagazine.com/2020/11/vue-applications-vue-testing-library/

    推荐阅读   




    推荐视频    

微信扫码关注该文公众号作者

戳这里提交新闻线索和高质量文章给我们。
相关阅读
Solo 推出完全集成的云原生应用程序网络平台7760万美元!6090万美元!麻州开放“社区一站式增长”应用程序在魁省的医保体系中,你的保险应该如何使用?母亲在养老院去世之后Bellevue轻轨出没请小心!底座缺陷、先开路线之争,一波三折的东线终于恢复测试如何使用 journalctl 查看和分析 systemd 日志(附实例) | Linux 中国駕長車縱橫五萬邁,巡看美國好河山(2)使用AppSync为在Dell PowerFlex上运行的应用程序提供拷贝数据管理精神炼金术 信仰的颠覆(六十一)美股IPO|移动广告服务提供商乐盟互动提交纳斯达克IPO申请,使用VIE架构,拟募资1800万美元走资派特色党还是为工农服务吗技术雷达最新动向:超级应用程序趋势不再、平台也需产品化如何使用机器学习来有效管理 Kubernetes 资源拟任副厅级领导职位公示期间,他被大量举报,相关部门初核后果断终止其任用程序授人以渔!现代化应用程序动手实训营手把手教你玩转容器平台!亚洲房颤患者如何使用NOAC?最新科学声明发布如何使用乳清蛋白粉【最后三天·优惠订阅】华为转型背后,中企如何适应世界新秩序?巨头再战音乐:TME测试WeBand,网易重上“妙时”,汽水音乐月活破千万如何使用领英(LinkedIn)用Venmo 和Zelle收款的注意了!新规明年一月生效!个人闲置物品转让 !超$600自动收到税单.纽约三重疫情来势凶猛,住院Vue 3是最佳选择吗? 耗时两周从Vue 2迁移到Svelte后:代码执行更快、体验更佳如何使用 Gateway 搭建网关服务及实现动态路由?韩国3月完成“萨德”部署程序?我外交部回应!韩总统称将考虑拥有核武器:“凭我们的科技,可以很快”找对象,长相、性格、家庭条件该怎么排序?我们如何使用 Next.js 将 React 加载时间缩短 70%如何使用Rust语言设计并开发一个领域编程语言公开课预告:企业如何使用 NVIDIA AI Enterprise 3.0 加速 AI 开发和部署马斯克入主推特如虎添翼,他的超级权力将被如何使用?如何使用洗碗机专用盐如何使用常见词提升口语水平?苹果将对 Foundation 框架用 Swift 重写并开源,网友:iOS/macOS 应用程序用吗?如何使用烤箱三女儿与父亲同行佛州(杰克逊维尔)早鸟报|亚马逊计划推出独立的体育应用程序;马斯克承认入主Twitter初期犯错;Meta元宇宙发展不妙未得回报......
logo
联系我们隐私协议©2024 redian.news
Redian新闻
Redian.news刊载任何文章,不代表同意其说法或描述,仅为提供更多信息,也不构成任何建议。文章信息的合法性及真实性由其作者负责,与Redian.news及其运营公司无关。欢迎投稿,如发现稿件侵权,或作者不愿在本网发表文章,请版权拥有者通知本网处理。