本教程包括
- 创建和设置一个Vue.js应用程序
- 为Vue组件编写自动化测试
- 建立一个持续集成管道
作为JavaScript社区的领先框架之一,Vue.js是一个渐进式框架,用于为Web用户界面构建可重用的组件。其直观的API和处理前端逻辑的强大灵活性只是Vue被全球开发者采用的两个原因。
在本教程中,我将带领你建立一个简单的列表应用程序,显示用户的名字和角色。我将告诉你如何为该应用编写测试。最后,你将配置一个持续集成管道以实现自动化测试。
先决条件
对于本教程,你将需要。
- 在您的系统上安装Node.js,最好是>=14.18.0版本。
- 一个CircleCI账户。
- 一个GitHub账户。
- 安装Vue CLI。本教程使用Vue CLI 5。
- 熟悉使用Vue.js构建应用程序。
开始学习
你将通过使用Vue CLI创建一个新的Vue.js项目。在终端上运行这个命令。
vue create vue-user-app
你会被提示回答几个问题。在本教程中,使用这里显示的回答。
- 请选择一个预设:手动选择功能
- 勾选你的项目所需的功能:Babel, Linter, Unit
- 选择一个Vue.js的版本,你想用3.x来启动项目
- 选择一个linter/formatter配置。只用ESLint来预防错误
- 选择额外的lint功能:保存时提示
- 选择一个单元测试解决方案:Jest
- 你喜欢把Babel、ESLint等的配置放在哪里?在专门的配置文件中
- 把这个作为预设保存起来,供以后的项目使用?没有
Vue CLI将按照你指定的方式安装Vue应用程序及其依赖项。
转到新项目,使用这些命令运行它。
cd vue-user-app
npm run serve
你可以在浏览器中查看该应用程序,网址是http://localhost:8080 。

这将渲染一个新的Vue.js应用程序的默认主页。你将在本教程的下一节中通过创建新的可重用组件来改变这一点。
使用CTRL + C停止应用程序的运行。
创建可重复使用的组件
Vue.js组件包含三个不同的部分,用于构建网络应用。它们是。
<template></template><script></script><style></style>
这些部分有助于为视图、业务逻辑和造型创建一个合适的结构。
创建用户组件
你将添加到应用程序的第一个组件是用于创建和列出用户。这个组件包含一个带有输入字段的表单,以接受特定用户的名字。当表单被提交时,输入字段的详细信息被推送到一个为测试目的而创建的假的users 数组。
首先,在./src/components 文件夹中创建一个名为UserList.vue 的新文件。打开这个新文件并粘贴这个内容。
<template>
<div class="container">
<div class="page-title">
<h3>{{ message }}</h3>
</div>
<div class="row">
<div
class="col-md-4"
v-for="user in users"
:key="user.id"
data-user="user"
>
<div class="m-portlet m-portlet--full-height">
<div class="m-portlet__body">
<div class="tab-content">
<div class="tab-pane active" id="m_widget4_tab1_content">
<div class="m-widget4 m-widget4--progress">
<div class="m-widget4__item">
<div class="m-widget4__img m-widget4__img--pic">
<img
src="https://bootdey.com/img/Content/avatar/avatar1.png"
alt=""
/>
</div>
<div class="m-widget4__info">
<span class="m-widget4__title"> {{ user.name }} </span>
<br />
<span class="m-widget4__sub">
{{ user.title }}
</span>
</div>
<div class="m-widget4__ext">
<button
@click="deleteUser(user)"
class="btn btn-primary"
data-cy="taskDelete"
id="deleteForm"
>
Delete
</button>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="row">
<form id="form" @submit.prevent="createUser">
<input id="new-user" v-model="newUser" class="form-control" />
</form>
</div>
</div>
</template>
这是<template></template> 部分,将用户列表渲染到视图中。它还包含一个输入字段,用于发布新用户的名字。
接下来,在</template> 标签的末尾粘贴这段代码。
<script>
export default {
props: ["message"],
data() {
return {
newUser: "",
users: [
{
id: 1,
name: "Anna Strong",
title: "Software Engineer",
},
{
id: 2,
name: "John Doe",
title: "Technical Writer",
},
],
};
},
methods: {
createUser() {
this.users.push({
id: 3,
name: this.newUser,
title: "Crypto Expert",
});
this.newUser = "";
},
deleteUser(user) {
const newList = this.users.filter((u) => user.id !== u.id);
this.users = newList;
},
},
};
</script>
这定义了一个users 数组,其中包含将在页面上呈现的假数据。createUser() 方法通过输入字段接收新用户的详细信息,并将其推送到users 数组中。你还定义了一个名为deleteUser() 的方法,它接受一个user 对象作为参数,并在调用时将其从用户列表中删除。
创建页眉组件
要为视图的标题部分创建一个组件,请进入./src/components 文件夹,创建一个名为NavBar.vue 的新文件。将这段代码粘贴到其中。
<template>
<nav class="navbar navbar-expand-lg navbar-dark bg-dark">
<div
class="collapse navbar-collapse justify-content-md-center"
id="navbarsExample08"
>
<ul class="navbar-nav">
<li class="nav-item active">
<a class="nav-link" href="#">
Users Listing App <span class="sr-only">(current)</span></a
>
</li>
</ul>
</div>
</nav>
</template>
更新应用程序组件
打开应用程序的AppComponent ,并更新它,包括与NavBar 和UserList 两个组件的链接。用这个替换它的内容。
<template>
<div>
<NavBar />
<UserList />
<div class="container"></div>
</div>
</template>
<script>
import NavBar from "./components/NavBar.vue";
import UserList from "./components/UserList.vue";
export default {
name: "App",
components: { NavBar, UserList },
};
</script>
<style>
body {
background: #eee;
}
#app {
font-family: Avenir, Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-align: center;
color: #2c3e50;
}
.page-title {
margin: 15px 15px;
}
.m-portlet {
margin-bottom: 2.2rem;
}
.m-portlet {
-webkit-box-shadow: 0 1px 15px 1px rgba(113, 106, 202, 0.08);
-moz-box-shadow: 0 1px 15px 1px rgba(113, 106, 202, 0.08);
box-shadow: 0 1px 15px 1px rgba(113, 106, 202, 0.08);
background-color: #fff;
}
.m-portlet .m-portlet__head {
border-bottom: 1px solid #ebedf2;
}
.m-widget4 .m-widget4__item {
display: table;
padding-top: 1.15rem;
padding-bottom: 1.25rem;
}
.m-widget4 .m-widget4__item .m-widget4__img {
display: table-cell;
vertical-align: middle;
}
.m-widget4 .m-widget4__item .m-widget4__img.m-widget4__img--logo img {
width: 3.5rem;
border-radius: 50%;
}
.m-widget4 .m-widget4__item .m-widget4__img.m-widget4__img--pic img {
width: 4rem;
border-radius: 50%;
}
.m-widget4 .m-widget4__item .m-widget4__img.m-widget4__img--icon img {
width: 2.1rem;
}
.m-widget4 .m-widget4__item .m-widget4__info {
display: table-cell;
width: 100%;
padding-left: 1.2rem;
padding-right: 1.2rem;
font-size: 1rem;
vertical-align: middle;
}
.m-widget4 .m-widget4__item .m-widget4__info .m-widget4__title {
font-size: 1rem;
font-weight: bold;
}
.m-widget4.m-widget4--progress .m-widget4__info {
width: 50%;
}
</style>
这包括一个<style></style> 部分,以包括应用程序的样式。
包括Bootstrap
打开公共文件夹中的index.html 文件,包括Bootstrap的CDN文件。这只是为了给页面提供一些默认样式。
<!DOCTYPE html>
<html lang="">
<head>
<meta charset="utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width,initial-scale=1.0" />
<link rel="icon" href="<%= BASE_URL %>favicon.ico" />
<link
rel="stylesheet"
href="https://cdn.jsdelivr.net/npm/bootstrap@4.6.1/dist/css/bootstrap.min.css"
integrity="sha384-zCbKRCUGaJDkqS1kPbPd7TveP5iyJE0EjAuZQTgFLD2ylzuqKfdKlfG/eSrtxUkn"
crossorigin="anonymous"
/>
<title><%= htmlWebpackPlugin.options.title %></title>
</head>
<body>
<noscript>
<strong
>We're sorry but <%= htmlWebpackPlugin.options.title %> doesn't work
properly without JavaScript enabled. Please enable it to
continue.</strong
>
</noscript>
<div id="app"></div>
<!-- built files will be auto injected -->
</body>
</html>
现在,用npm run serve 再次运行该应用程序。访问https://localhost:8080 。
现在你的应用程序已经启动并运行,你可以开始对UserList 组件进行单元测试。
Vue.js组件的单元测试
有很多很多JavaScript应用程序的测试框架。Jest作为最受欢迎的框架之一脱颖而出。对于Vue.js,Vue Test Utils(VTU)是首选的测试库。这是有道理的,因为VTU测试库是建立在Jest之上的。它被设计为通过提供实用功能来简化Vue.js组件的测试。
当你创建这个项目并选择Jest作为单元测试解决方案时,Vue CLI安装了vue-test-utils ,jest ,和其他测试库。以下目录也被创建了。
test/unit:这个目录将放置所有的单元测试。一旦发出测试命令,Jest将在这里搜索你的单元测试文件。
编写应用程序的测试
在本节中,我们将为UserList 组件编写单元测试。在该组件中,我们要。
- 挂载该组件,并检查它是否能渲染传递给它的道具。
- 在组件中寻找元素并渲染用户列表。
- 提交一个表单,然后创建一个新的用户并将其添加到现有用户列表中。
首先,到test/unit 文件夹中,将example.spec.js 文件重命名为user.spec.js 。打开该文件,将其内容替换为以下内容。
import { mount } from "@vue/test-utils";
import UserList from "@/components/UserList.vue";
describe("User List component unit tests: ", () => {
it("renders props when passed", () => {
const message = "new message";
const wrapper = mount(UserList, {
props: { message },
});
expect(wrapper.text()).toMatch(message);
});
test("Renders the list", () => {
const wrapper = mount(UserList);
const name = "Anna Strong";
const user = wrapper.get('[data-user="user"]');
expect(user.text()).toContain(name);
expect(wrapper.findAll('[data-user="user"]')).toHaveLength(2);
});
test("creates a user", async () => {
const wrapper = mount(UserList);
const newName = "John Doe";
await wrapper.get('[id="new-user"]').setValue(newName);
await wrapper.get('[id="form"]').trigger("submit");
expect(wrapper.findAll('[data-user="user"]')).toHaveLength(3);
});
});
在这个文件中,我们从vue-test-utils 库中导入了一个名为mount 的函数,以帮助我们装载一个UserList 组件的实例。
我们首先写了一个测试,断言该组件可以渲染一个从父组件传入的道具。接下来,我们在UserList 组件的视图中锁定了数据属性,确保它包含一个用户的具体名字,并确保它渲染了users 数组中的默认长度。
最后,我们创建了一个测试函数,以确保在该组件中可以创建一个新的用户。
在本地运行测试
为了确认定义的测试是否通过,从终端输入这个命令。
npm run test:unit
这是终端的输出。
> vue-user-app@0.1.0 test:unit
> vue-cli-service test:unit
PASS tests/unit/user.spec.js
User List component unit tests:
✓ renders props when passed (33 ms)
✓ Renders the list (19 ms)
✓ creates a user (27 ms)
Test Suites: 1 passed, 1 total
Tests: 3 passed, 3 total
Snapshots: 0 total
Time: 0.924 s, estimated 1 s
Ran all test suites.

在下一节中,你将使用CircleCI自动进行测试。
自动测试
在本节中,你将为你的项目的持续集成管道创建一个配置文件。
在项目的根部创建一个.circleci 文件夹,并在其中创建一个名为config.yml 的新文件。添加这个内容。
version: 2.1
jobs:
build-and-test:
working_directory: ~/project
docker:
- image: cimg/node:17.4.0
steps:
- checkout
- run:
name: Update NPM
command: "sudo npm install -g npm"
- restore_cache:
key: dependency-cache-{{ checksum "package-lock.json" }}
- run:
name: Install Dependencies
command: npm install --legacy-peer-deps
- save_cache:
key: dependency-cache-{{ checksum "package-lock.json" }}
paths:
- ./node_modules
- run:
name: Run test for the application
command: npm run test:unit
workflows:
build-and-test:
jobs:
- build-and-test
这个文件定义了一个作业,用于为你的项目构建和运行测试命令。这个作业
- 从CircleCI Docker镜像注册表中调取
cimg/node:17.4.0Docker镜像 - 使用该镜像来安装项目的所有依赖项
- 运行测试
现在,配置文件已经被正确设置,你需要在GitHub上设置一个仓库,并将项目链接到CircleCI。查看推送项目到GitHub的步骤说明。
在CircleCI上设置项目
用链接的GitHub账户登录您的CircleCI账户,在项目的仪表板上查看您的所有仓库。搜索vue-user-app 项目,点击设置项目继续。

你会被提示选择一个配置文件。在你的 repo 中选择.circleci/config.yml 文件,并输入存储你的代码的分支名称。点击 "设置项目"来启动工作流。

这将初始化工作流并为你的项目运行测试。

总结
在本教程中,我们用Vue.js构建了一个列表应用程序,并涵盖了为其组件编写单元测试的必要步骤。然后,我们使用CircleCI基础设施来配置一个持续集成管道,以实现测试的自动化。