使用Cypress进行前端测试驱动开发:LINE案例研究

大家好,我是Line产品开发总部的 Youngjin Jang。

你在进行前端开发时会编写测试代码吗?由于工作性质的原因,前端开发人员需要在开发进度的后半段综合可交付成果(规格、设计、API)并创建最终产品,因此由于时间紧迫而很难编写测试代码。相反,在开发进度的前半部分,你可能会比其他职位拥有相对较多的时间。为什么不利用这段时间编写测试呢?

本文将介绍测试驱动开发的基本概念、使用 Cypress 的测试驱动开发方法,以及我们在开发 LINE Doctor 前端时如何实际使用测试驱动开发。

什么是 LINE Doctor?

LINE Doctor是一项在线医疗服务,允许用户通过LINE在家中接受体检、接受处方和药物。可靠性对于LINE Doctor来说非常重要,因此我们在开发前端时采用测试驱动开发来保证质量。

测试驱动开发概述

测试驱动开发是在开发的早期阶段首先编写测试,然后编写代码以使测试用例通过的过程。

首先编写失败的测试代码,然后实现该功能以使测试通过并重构代码。通过重复这个循环,可以构建高质量的代码库。

1.创建测试代码:首先编写函数的测试用例

2.实施:实施该功能直到测试通过

3.重构:整理已实施的代码

使用 Cypress 实践测试驱动开发

Cypress (https://www.cypress.io/)是一款前端测试工具,可以实现在真实浏览器中运行测试;Cypress 易于安装,易于创建测试代码,并可以让你实时检查测试结果。此外,Cypress 测试代码可在真实浏览器中运行,便于调试。Cypress 的这些功能使前端测试驱动开发成为可能。

在这里我们将安装 Cypress 并看看它如何进行测试驱动开发。首先,使用 npm 安装 Cypress 并启动 Cypress。

npm install cypress --save-dev

npx cypress open

当启动Cypress时,Cypress程序将如下所示执行。使用 Cypress 的测试驱动开发基于 E2E 测试。单击“E2E 测试”开始在 Google Chrome 中进行测试。

图片

编写首先失败的测试代码。例如,假设你的任务管理服务实现了一个规范,即当用户访问任务列表页面时应显示任务列表。首先,创建cypress/e2e/todo.cy.js 文件并编写测试代码,如下所示。

// cypress/e2e/todo.cy.js



describe('任务管理', () => {

it('Task list is displayed', () => {

// 访问页面

cy.visit('http://localhost:3000/');



// 检查页面中是否有 data-testid 属性为 "todo-list "的元素

cy.get('[data-testid="todo-list"]').should('exist'); // 此测试失败,因为尚未实现。

});

});

该测试代码验证当用户访问该页面时,“任务列表”是否显示在屏幕上。

当你运行测试时,可以看到测试失败,如下所示。

图片

为了通过测试,我们将实现一个显示任务列表的 UI。

<! -- index.html -->



<div data-testid="todo-list">

<! -- タスクリストが表示される場所 -->

</div>

实现后,可以查看Cypress,看到测试通过了,如下图。

图片

接下来是重构阶段,但是由于没有足够的代码需要重构,所以我在这里跳过它。

随着我们不断开发任务管理服务,我们可能会需要添加任务、完成任务等新的需求。在这种情况下,可以通过重复循环来继续进行测试驱动开发,首先添加测试代码,然后继续实施,如下所示。​​​​​​​

// cypress/integration/todo_spec.js



describe('タスク管理', () => {



// ... 以前のテストコード



it('タスクを追加する', () => {

// ページにアクセス

cy.visit('http://localhost:3000/');



// タスクを入力した後、エンターキーを押す

cy.get('[data-testid="new-todo"]').type('新しいタスク{enter}');



// タスクリストに新しいタスクが追加されたことを確認

cy.get('[data-testid="todo-list"]').should('contain', '新しいタスク');

});

});

LINE Doctor 案例研究

LINE Doctor有一项功能,允许用户在在线咨询后到自己选择的药房取药。如果所选药店距离用户地址超过15公里,可能无法亲自去取药,因此有一个功能,显示弹出窗口询问用户是否确实要取药在那家药店。我将介绍我是如何进行该功能的实际测试驱动开发的。

1.创建测试代码

首先,确定创建测试代码所需的信息。由于前端无法检查用户选择的药店距离用户地址是否超过15公里,因此在与后端开发人员讨论API后,我们决定API接口如下。使用此 API,前端可以将用户的地址和所选药房 ID 发送到后端,以检查距离是否超过 15 公里。​​​​​​​

// このAPIは実際に使われているAPIではなく、加工したAPIです。



// request

GET /v1/is-pharmacy-nearby

{

"userAddress": "ユーザーの住所"

"pharmacyId": "薬を受け取る薬局のID"

}



// response

true || false

然后,用测试代码替换规范并创建它。编写测试代码时,首先编写一个作为基本功能的案例,然后添加从该案例派生的案例。对于前端无法控制的方面,例如 API 幕后发生的行为,请编写测试代码,重点关注传递给 API 的参数以及是否在适当的时间请求 API。在编写测试代码时,我们的目标是确保与利益相关者的所有讨论都反映在测试代码中。测试代码利用唯一的特性来避免运行所有测试用例,避免由于测试执行速度而导致生产力损失。

describe.only('選択した薬局とユーザーの住所の距離確認', () => {

// 基本になるテストケース

it('薬局がユーザーの住所から15km以上の場合、ポップアップを表示する', () => {

// バックエンドエンジニアと議論したAPI Interfaceをモックする

// 薬局がユーザーの住所から15km以上の場合なので、APIはfalseを返す

cy.intercept('GET', `/v1/is-pharmacy-nearby**`, 'false').as(

'fetchIsPharmacyNearby'

);



// ポップアップを表示するページにアクセスする

cy.visit(`/treatment/review`);



// 予約を完了させる

cy.get('[data-testid=confirm_reservation]').click();



// ポップアップが表示されることを確認する

cy.get('[data-testid="common_modal"]').should('exist');

cy.get('[data-testid="common_modal_description"]').should(

'contain',

'お薬を受け取る薬局の住所がご自宅住所から離れています。このまま予約を完了しますか?'

);



// APIを呼ぶときに正しいパラメータをわたしたか確認する

cy.wait('@fetchIsPharmacyNearby').then(({ request }) => {

const searchParams = new URL(request.url).searchParams;

expect(searchParams.get('userAddress')).to.equal('xxx');

expect(searchParams.get('pharmacyId')).to.equal(`999`);

});

});



// 派生したケース

it('薬局がユーザーの住所から15km未満の場合、ポップアップを表示しない', () => {

/// 薬局がユーザーの住所から15km未満の場合なので、APIはtrueを返す

cy.intercept('GET', `/v1/is-pharmacy-nearby**`, 'true');



// ...省略



// ポップアップが表示されないことを確認する

cy.get('[data-testid="common_modal"]').should('not.exist');

});

});

在我们的基本案例中,我们首先使用cy.intercept来确保 API 结果始终确定用户的地址距离药房至少 15公里。然后使用cy.get找到预约完成按钮,使用cy.click完成预约。此时, cy.should验证屏幕上是否显示了预期的结果(确认弹出窗口) 。

在派生情况下,将 API 结果设置为始终小于 15 公里,并验证当你按“完成预订”时不会出现确认弹出窗口。

当你添加测试代码并运行 Cypress 时,你可以看到测试失败,因为尚未实现显示弹出窗口的功能,因此未显示弹出窗口。

图片

2. 实施

现在我们来编写实际的实现代码来通过测试。当用户按下预约按钮时,我们通过API检查用户选择的药店距离用户的地址是否超过15公里。如果 API 结果为 false,则显示弹出窗口。

// LINEドクターのフロントエンドはVueを利用しているので、サンプルコードはVueのコードになります。





<template>

<main>

<!-- ... -->



<button data-testid="confirm_reservation" @click="handleClickConfirm">

予約する

</button>



<!-- ... -->

</main>

</template>



<script>

export default {

// ...

methods: {

async handleClickConfirm() {

// ...



const response = await this.$axios.get(

'/v1/is-pharmacy-nearby',

{

params: {

userAddress: this.userAddress,

pharmacyId: this.pharmacyId,

},

}

);

if (!response.data) {

await this.$modal.open({

text: 'お薬を受け取る薬局の住所がご自宅住所から離れています。このまま予約を完了しますか?',

});

}



// ...

},

},

};

</script>

添加实现代码后,可以再次运行Cypress测试,确认测试成功。

图片

3. 重构

接下来是重构阶段。在实现过程中,我在预订完成按钮的点击处理程序中编写了代码,但是预订完成按钮的处理程序包含多个处理逻辑,这使得它的可读性较差。因此,我们将相关逻辑分离到一个单独的函数中,并将其重构为从按钮的单击处理程序中调用。

<template>

<main>

<!-- ... -->



<button data-testid="confirm_reservation" @click="handleClickConfirm">

予約する

</button>



<!-- ... -->

</main>

</template>



<script>

export default {

// ...

methods: {

async handleClickConfirm() {

// ...



if (!await this.isPharmacyNearby()) {

await this.$modal.open({

text: 'お薬を受け取る薬局の住所がご自宅住所から離れています。このまま予約を完了しますか?',

});

}



// ...

},

async isPharmacyNearby() {

const response = await this.$axios.get(

'/v1/is-pharmacy-nearby',

{

params: {

userId: this.userId,

pharmacyId: this.pharmacyId,

},

}

);



return response.data;

}

},

};

</script>

这样,我们在开发LINE Doctor的UI时,首先编写测试代码,编写通过测试代码的实现代码,然后进行重构。

概括

本文介绍了测试驱动开发的基础知识、如何使用 Cypress 实践测试驱动开发,以及如何通过 LINE Doctor 中的具体开发示例实际应用测试驱动开发。测试驱动开发是一种支持高质量软件开发的强大方法,而 Cypress 则让前端测试驱动开发变得更加容易。

大家何不尝试一下测试驱动开发,让自己的前端开发更可靠呢?

最后: 下方这份完整的软件测试视频教程已经整理上传完成,需要的朋友们可以自行领取【保证100%免费】

​​​软件测试面试文档

我们学习必然是为了找到高薪的工作,下面这些面试题是来自阿里、腾讯、字节等一线互联网大厂最新的面试资料,并且有字节大佬给出了权威的解答,刷完这一套面试资料相信大家都能找到满意的工作。

在这里插入图片描述

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值