快照测试是 Jest 中的一种测试,它监视代码中的回归并用作集成测试。第一个意思是,如果您向项目添加更多代码和一些小中断,快照测试可以捕获它。第二个意味着快照测试是一种确保整个组件按照您希望的方式运行的方法。
快照测试的工作方式是在您第一次运行时jest
,生成 DOM 的快照。在测试套件的后续运行中,构建的 DOM 会与这些快照进行比较。由于您可能已经更改了代码,因此您的快照仍然与第一次生成的快照相匹配,这告诉您事情仍在进行。
自然会出现一些问题:如果我对您的程序进行重大更改导致不同的 DOM 内容怎么办?Jest 允许您生成新的快照,这样的场景就可以保证这一点。如果我的页面上有不确定的内容怎么办?有多种方法可以处理这个问题,我们很快就会看到这个!
应用程序设置
我们现在将设置我们的应用程序。转到我们关于使用 Jest 测试 Vue的教程的设置部分,以设置一个简单的应用程序进行测试。您的App.vue
文件可能如下所示:
<template>
<div id="app">
<div>
<h3>Let us test your arithmetic.</h3>
<p>What is the sum of the two numbers?</p>
<div class="inline">
<p>{{ x1 }} + {{ x2 }} =</p> <input v-model="guess"> <button v-on:click="check">Check Answer</button>
</div>
<button v-on:click="refresh">Refresh</button>
<p>{{message}}</p>
</div>
</div>
</template>
<script>
export default {
name: 'App',
data() {
return {
x1: Math.ceil(Math.random() * 100),
x2: Math.ceil(Math.random() * 100),
guess: "",
message: ""
}
},
methods: {
check() {
if (this.x1 + this.x2 === parseInt(this.guess)) {
this.message = "SUCCESS!"
} else {
this.message = "TRY AGAIN"
}
},
refresh() {
this.x1 = Math.ceil(Math.random() * 100);
this.x2 = Math.ceil(Math.random() * 100);
}
}
}
</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;
}
.inline * {
display: inline-block;
}
img {
height: 350px;
}
</style>
这是我们开始的app.spec.js
样子:
import { mount } from "@vue/test-utils";
import App from "./../src/App.vue";
describe("App", () => {
// Inspect the raw component options
it("has data", () => {
expect(typeof App.data).toBe("function");
});
});
describe("Mounted App", () => {
const wrapper = mount(App);
test("is a Vue instance", () => {
expect(wrapper.isVueInstance()).toBeTruthy();
});
it("renders the correct markup", () => {
expect(wrapper.html()).toContain(
"<p>What is the sum of the two numbers?</p>"
);
});
// it's also easy to check for the existence of elements
it("has a buttons", () => {
expect(wrapper.contains("button")).toBe(true);
});
it("renders correctly with different data", async () => {
wrapper.setData({ x1: 5, x2: 10 });
await wrapper.vm.$nextTick();
expect(wrapper.text()).toContain("10");
});
it("button click without correct sum", () => {
expect(wrapper.vm.message).toBe("");
const button = wrapper.find("button");
button.trigger("click");
expect(wrapper.vm.message).toBe("TRY AGAIN");
});
it("button click with correct sum", () => {
wrapper.setData({ guess: "15" });
const button = wrapper.find("button");
button.trigger("click");
expect(wrapper.vm.message).toBe("SUCCESS!");
});
});
请记住,这it
只是test
Jest 中的别名。运行npm run test
,所有测试都应该通过。
让我们开始快照测试!
运行npm install --save-dev jest-serializer-vue
然后添加以下内容package.json
{
...
"jest": {
"snapshotSerializers": ["jest-serializer-vue"]
},
...
}
向第二个描述块添加一些代码。
it('renders correctly', () => {
const wrapper = mount(App)
expect(wrapper.element).toMatchSnapshot()
})
运行您的测试并注意第一次运行测试时您应该如何看到“1 个快照已写入”。请注意,__snapshots__
已在 旁边创建了一个名为的目录app.spec.js
。
随意看看快照文件,它有一个以.snap
扩展名结尾的文件;您会注意到组件的整个模板部分都已复制,但带有前缀的属性除外v-
。
再次运行您的测试。
错误!
为什么?!
如果您在终端中检查快照测试的输出,就会很清楚原因:我们在页面上随机生成了数字。您还应该能够看到快照中的数字是什么。继续并data
在您安装组件时通过传递将它们替换到您的测试中;您传递的函数将合并到组件自己的data
.
一旦你再次通过它,它应该看起来像这样:
it('renders correctly', () => {
const wrapper = mount(App, {
data() {
return {
x1: 37,
x2: 99
}
}
})
expect(wrapper.element).toMatchSnapshot()
})
另一种方法是在我们的代码中为非确定性函数编写一个模拟函数。在我们的例子中就是Math.random()
.
你会得到如下内容:
it('renders correctly with mock', () => {
Math.random = jest.fn(() => .37);
const wrapper = mount(App)
expect(wrapper.element).toMatchSnapshot()
})
假设我们想将标题移到页面上的照片上方。这是对 Vue 组件的简单修改,所以继续这样做。再次尝试运行您的测试套件。
错误!
它失败了,因为我们的快照的页面排列方式不同。我们必须更新快照的那部分,我们可以通过运行npm test -- -u
.
现在我们的测试又通过了。
成功!
如果您想以交互方式更新快照,您可以运行npm test -- -i
.
结论
快照对于跟上应用程序界面的任何意外更改非常有用。快照应该像任何其他代码一样被检入 Git。如果测试失败,请在反射性更新快照之前检查发生了什么。
在测试 Vue 应用程序时,快照测试应该非常有用,尤其是当它们变得更加复杂时。祝你好运!