如何使用Vue测试库测试应用程序?
新钛云服已累计为您分享714篇技术干货
Vue测试库可以帮助您通过模拟用户与APP之间的交互方式来测试您的应用程序。
在本文中,我们将使用Vue测试库来测试Vue应用程序,这是一个轻量级的库,它强调从用户的角度来测试您的前端应代码。
· 了解vue相关知识
· 熟悉测试APP的UI
// 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测试库是什么?
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测试库的原理
<button data-testid="checkoutButton">Check Out</button>
开始使用Vue测试库
vue create vue-testing-library-demo
vue add unit-jest
"test:unit": "vue-cli-service test:unit",
npm run test:unit
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)
})
})
npm uninstall @vue/test-utils --save-dev
npm install @testing-library/vue --save-dev
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中是否存在具有“新消息”文本内容的元素。
我们的演示应用
<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>
<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>
· 用户可以看到产品名称吗?
· 用户能看到产品价格吗?
· 用户能否增加产品数量?
· 用户可以减少产品数量吗?
· 用户可以随着数量的变化实时查看更新的总价吗?
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)
})
it('renders initial quantity as 1', () => {
const { getByDisplayValue, getByText } = render(CheckOut, {
props: { product }
})
getByDisplayValue(1)
})
it('increments product quantity', async () => {
const { getByDisplayValue, getByText } = render(CheckOut, {
props: { product }
})
const incrementQuantityButton = getByText('+')
await fireEvent.click(incrementQuantityButton)
getByDisplayValue(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)
})
总结
推荐阅读
推荐视频
微信扫码关注该文公众号作者
戳这里提交新闻线索和高质量文章给我们。
来源: qq
点击查看作者最近其他文章