前端测试:e2e测试

article/2025/10/17 2:38:52

为什么进行测试

你是否有以下烦恼:

  • 当你加班加点完成一个功能后,提交给测试部,立马返回几个bug

  • 当你修改完bug后,并检查了好几遍,确保无误后,提交给测试部,有返回几个bug

    ……

对于以上情境,你是否有过疑问,为什么检查都没问题了还是出现bug?以上这些都是因为没有做好测试。

你可能会问,做了呀,都检查好几遍了。的确,你是测试了,但是你并没有完成测试的闭环。你可能完成测试的一部分,其他的部分并没有完成。既然你说我没完成测试,那何为测试,又怎么进行测试?

什么是测试?

对于前端来说,测试主要是对HTML、CSS、JavaScript进行测试,以确保代码的正常运行。

常见的测试有单元测试、集成测试、端到端(e2e)的测试。

  • 单元测试:对程序中最小可测试单元进行测试。我们可以类比对汽车的测试,在汽车组装之前需要对零件进行测试,这种情况下就和单元测试一致。只有零件正常才会进行下一步的组装
  • 集成测试:对多个可执行单元组成的整体进行测试。类比于汽车的测试,就相当于测试发动机之前,需要把发动机所需的零件组装在一起对组装后的发动机这个整体进行测试。
  • 端到端的测试(e2e):从服务端到客户端的测试。这种测试是对服务端和客户端组成的整个系统进行测试,它是能够执行完整流程的测试。

既然知道了有这些测试种类,接下来就说说这些测试应当如何实现。

如何进行测试

测试的方式可以分为人工测试、自动测试。

人工测试:就是让测试部的人员根据业务流程进行操作当某一步或几步出现问题就说明这部分代码有问题。这种测试方式有很明显的不足:

  1. 它只能测试测试人员看得见的部分,对于测试人员看不见的部分不能测试。比如一些内部的工具函数、逻辑代码等,这些很可能存在问题。

自动测试:利用写好的代码对代码进行测试。这种测试能够弥补人工测试的不足,它的颗粒度是代码级别的,能够准确地识别某个方法的错误

由此,在实际的开发过程中我们可以采用人工测试+自动测试的方式进行测试,力求100%的覆盖测试目标。人工测试暂且不谈,我们先谈谈自动测试的方式实现单元测试、集成测试、e2e测试。本篇博客先讲e2e测试。

e2e测试

实现e2e测试的库和框架有很多,这篇文章以Cypress为例进行讲解。

cypress简介

Cypress是基于JavaScript语言的前端自动化测试工具,无需借助外部工具,自集成了一套完整的端到端测试方法,可以对浏览器中运行的所有内容进行快速、简单、可靠的测试,并且可以进行接口测试

cypress的特点

  • 时间穿梭:Cypress会在测试运行时拍摄快照。只需将鼠标悬停在命令日志上,即可清楚了解每一步都发生了什么
  • 可调试性:无需揣测测试失败原因。直接使用浏览器的DevTools进行调试。清晰的错误原因和堆栈跟踪让调试能够更加快速便捷
  • 实时重载:每次对测试代码进行更改,Cypress都会实时执行新的命令,自动重新加载页面进行测试
  • 自动等待:无需在测试中添加等待。在执行下一条命令或断言前Cypress会自动等待元素加载完成,异步操作不再是问题
  • 间谍,存根和时钟:Cypress允许验证并控制函数行为,Mock服务器响应或更改系统时间,更便于进行单元测试
  • 网络流量控制:Cypress可以Mock服务器返回结果,无须连接后端服务器即可实现轻松控制,模拟网络请求
  • 运行结果一致性:Cypress架构不使用Selenium或Webdriver,在运行速度、可靠性、测试结果一致性上均有良好的保障
  • 截图和视频:Cypress在测试运行失败时自动截图,在使用命令运行时录制整个测试套件的视频,轻松掌握测试运行情况

cypress安装

npm install cypress -D

安装完毕后,执行 npx cypress open 会打开一个窗口根据自己项目使用的框架和打包器进行选择,选择完毕后会自动生成配置文件及其相关文件,然后选择对应的测试类型,这里选择e2e测试。选择完毕后就可以运行测试套件。

cypress自定义mount命令

对于vue项目来说,一般都会使用vue-router和vuex两个插件,因此在测试的时候需要把这两个插件挂载到vue实例上。

挂载router

import {mount} from 'cypress/vue'import router from '../../src/router';
Cypress.commands.add('mount',(component, options={})=>{options.global.plugins = options.global.plugins || [];
options.global.component = options.global.component || {};if(!options.router){options.router = router;}options.global.plugins.add({install(app){app.use(options.router) ;}})return mount(component,options);
})

挂载vuex

import {mount} from 'cypress/vue'
import store from '../../src/store';
Cypress.commands.add('mount',(component,options={})=>{options.global.plugins = options.global.plugins ||[];options.global.component = options.global.component || {};const {store = store,...mountOption,} = options;options.global.plugins.push({install(app){app.use(store);}});return mount(component,mountOption);
})

挂载全局组件

import {mount} from 'cypress/vue'
import {BaseButton} from '../../src/components/BaseButton.vue'
Cypress.commands.add('mount',(component,options)=>{options.global.component =  options.global.component || {};options.global.component.BaseButton = BaseButton;return mount(component, options);
});

配置文件(cypress.config.js)

下面列举一些常用的配置项,具体配置说明访问配置说明

const {defineConfig} = require('cypress');
module.exports = defineConfig({// e2e测试e2e:{},// 组件测试component:{},// 取消测试时录制视频video:false,// 取消测试失败时截屏screenshotOnRunFailure:false
});

语法

cypress框架的测试文件以.spec.js为后缀,测试时的目录可以通过cypress.config.js进行配置

mount()方法用于挂载组件

import HelloWorld from './HelloWorld.vue';
describe('description',()=>{it('description',()=>{cy.mount(HelloWorld);});
});

cy.contains()方法用于检测页面中的元素的内容是否与指定的内容相同

it('测试 contains',()=>{cy.contains('hello world');
});

浏览器导航操作

cy.visit(url):访问url,只能访问返回html文件的url

cy.go():

cy.back():

cy.reload(boolean):true:不需要缓存,false:需要缓存

cy.url():获取网页的url

cy.title():获取网页的title

元素定位

运行测试代码之后点击playground按钮用鼠标点击元素然后复制界面上方输入框的内容就可以得到一行代码。

上下级关系

within():在指定的元素中查找元素

cy.get('form').within((form)=>{// 找form的第一个inputcy.get('input:first').type('username');
})

context():

cy.context()

children(selector):查找子元素

parent():获取元素的父元素

sibling():查找同级元素

prev():找到前一个元素

let pwd_el = cy.get('.username').sibiling('input');
pwd_el.prev('input');

next():找到下一个元素

let pwd_el = cy.get('.username').sibiling('input');
pwd_el.prev('input');

元素的输入操作

focus():输入框聚焦事件

cy.get('.password').focus().type('123');

blur():输入框失焦事件

cy.get('.username').blur();

submit():只有form表单才能调用

cy.get('.form').submit();

元素的点击操作

click():单击元素

dbclick():双击元素

rightclick():右击元素

单选和多选

check():选中单选框或多选框

cy.get('.radio').check();
cy.get('.checkbox').check();
// 强制选择,在禁用状态下依然可用
cy.get('.radio').check(true);
// 强制取消选择
cy.get('.radio').cehck(false);
// 选中其中的一个
cy.get('.checkbox').check('checkboxvalue');
cy.get('.radio').check('radiovalue');
// 选中其中的多个
cy.get('.checkbox').check('checkboxvalue1','checkboxvalue2');

下拉框

select():选中下拉框的指定项

// 通过选项的value值选中选项
cy.get('.select').select('selectvalue');
// 通过选项的文本值选中选项
cy.get('.select').select('selectText');
// 选中多个
cy.get('.multipleSelect').select(['selectText1','selectText2'])

窗口滚动

scrollIntoView():把元素滚动到可视范围内

scrollTo():滚动窗口到指定位置

cy.get('.input').scrollIntoView();
// 滚动到顶端
cy.scrollTo('top');
// 滚动到最底部
cy.scrollTo('bottom');
// 滚动到指定位置
cy.scrollTo(100,200)

测试样式

如果你的项目中的html文件中有引入其他样式,那么在cypress/support/component-index.htmlz中也需要引入相同的样式。

如果你在项目中的main.js中引入其他样式,那么你在cypress/support/component.js中也需要引入相同样式。

例如,我的项目中使用view-ui-plus第三方组件库,引入了它的样式,那么在cypress/support/component.js中就需要引入该样式。
我的项目中的main.js文件
在这里插入图片描述
cypress文件夹下的component.js文件
在这里插入图片描述

测试事件

在测试文件中,为组件提供一个props,props中注册事件名和事件响应函数

import Input from '../components/Input.vue'describe('测试 input',()=>{it('测试 change',()=>{const changeHandler =  (v)=>{console.log(v);} cy.mount(Input,{props:{onChange:changeHandler}});cy.get('.input').type('hello world');cy.get('@onChange').should('have.been.calledWidth',1);});
});

Cypress的原理

  • 大多数测试工具(如Selenium)通过在浏览器之外运行并在网络上执行远程命令来运行。赛普拉斯恰恰相反。Cypress在与应用程序相同的运行run loop中执行。
  • Cypress后面是一个Node服务器进程。Cypress和Node进程不断地代表彼此进行通信、同步和执行任务。访问这两个部分(正面和背面)使我们能够实时响应应用程序的事件,同时在浏览器之外处理需要更高权限的任务。
  • Cypress还通过实时读取和更改网络流量在网络层进行操作。这使得Cypress不仅可以修改进出浏览器的所有内容,还可以更改可能干扰其自动化浏览器能力的代码。
  • 由于Cypress是在您的机器上本地安装的,因此它还可以进入操作系统执行自动化任务。这使得执行诸如截屏、录制视频、常规文件系统操作和网络操作等任务成为可能。

Cypress 运行测试的大致流程

  1. 运行测试后,Cypress 使用 webpack 将测试代码中的所有模块 bundle 到一个 js 文件中
  2. 然后,运行浏览器,并且将测试代码注入到一个空白页中,然后它将在浏览器中运行测试代码【**可以理解成:**Cypress 将测试代码放到一个 iframe 中运行】
  3. 每次测试首次加载 Cypress 时,内部 Cypress Web 应用程序先把自己托管在本地的一个随机端口上**【如:http://localhost:65874】**
  4. 在识别出测试中发出的第一个 命令后,Cypress 会更改本地 URL 以匹配你远程应用程序的 Origin**【满足同源策略】,这使得你的测试代码和应用程序可以在同一个 Run Loop 中运行**

cypress的组件测试和e2e测试的区别

主要区别在于,Cypress组件测试使用开发服务器构建组件,而不是在一个完整的网站中进行渲染,这与覆盖相同代码路径的端到端测试相比,可以更快地进行测试,减少对基础设施的依赖。

Cypress运行端到端测试的方式与用户使用真实浏览器、访问URL、查看内容、点击链接和按钮等与您的应用程序交互的方式相同。以这种方式进行测试有助于确保您的测试和用户体验相同。

组件测试与端到端测试的不同之处在于,组件可以自行“安装”和测试,而不是访问URL来获取整个应用程序。这使您可以专注于只测试组件的功能,而不用担心将组件作为更大应用程序的一部分进行测试时的其他细微差别。


http://chatgpt.dhexx.cn/article/iUKoaHGv.shtml

相关文章

【AUTOSAR-E2E】-1.1-End-to-End通信保护介绍(Functional Safety功能安全相关)

目录 1 常见的通讯故障以及E2E机制能够检出的通讯故障 2 Functional safety功能安全对通信的要求 3 通信故障的原因 3.1 软件故障 3.2 随机硬件故障 3.3 外部影响、环境压力 4 常见的“E2E通讯保护”解决方案 4.1 无E2E保护的信号数据流示例 4.2 E2E Protection Wrapper解决方案…

Autosar BSW层CAN通讯开发------08(Autosar的E2E开发-----以E2E Profile01为例)

Crc校验在CAN报文中的实际应用介绍: Crc在报文传输过程中的实际应用如下(在汽车中,Crc一般是对8个字节进行校验,目前我接触到的是这样): ECU-A和ECU-B之间进行CAN报文的传输,双方规定ECU-A发出的…

功能安全专题之端到端(E2E) 的通信保护

本文来自AUTOSAR技术资料。 前言 功能安全(Functional Safety)是一项系统特性,由于基于功能安全的设计会影响到系统设计,所以从系统开发初始阶段就要进行考虑。由于软件的复杂度会影响 到功能安全的设计,所以在AUTOS…

AUTOSAR的E2E通信安全

导语:近期项目中遇到一些E2E的诊断故障,涉及到整车需求和AutoSAR配置,对这个概念重新做了下梳理,与大家交流。由于E2E机制比较成熟,本文章内容更多出自于AutoSAR标准、ISO 26262 和相关文献,这里只捡重点和…

E2E通信保护协议学习笔记

E2E通信保护协议学习笔记 最近在做功能安全方面工作,想了解E2E保护的问题。本文试着说明两个点: 功能安全需要考虑通信失效造成的影响,因此E2E通信保护协议被提出,以满足功能安全要求; 简单介绍E2E通信保护协议机制。…

什么是 E2E 保护 ?

安全在每个领域都是一个永恒的话题,汽车也不例外,而随着最近几年汽车电动化、智能化和网联化的发展,汽车安全也越来越受到用户及开发人员的重视,安全的要素也是多方面的,例如用户可能关心在使用车机系统时的隐私安全、…

HVS颜色空间的提取

在日常的图片处理中,常常要把RGB转成HVS,然后再提取色调、亮度、饱合度通道图片进行操作,网上大多介绍都只是提到转换,如果提取都不准确,我这里记录一下准确提取的方法。V,S提取只要将值乘255就可以&#x…

matlab绘制hsv色轮图

% 生成网格 tListlinspace(0,2.*pi,300); rListlinspace(0,1,100); [theta,R]meshgrid(tList,rList);% 角度及半径转换为坐标 Xcos(thetapi).*R; Ysin(theta).*R; Zzeros(size(X));% 构造hsv网格并转换为rgb网格 hsvMeshcat(3,theta./2./pi,ones(size(R)),R); rgbMeshhsv2rgb(h…

图像融合:Exposure Fusion Using Boosting Laplacian Pyramid

Exposure Fusion Using Boosting Laplacian Pyramid 文章目录 Exposure Fusion Using Boosting Laplacian PyramidJND ModelLuminance AdaptationContrast MaskingOverall JND Model A Hybrid Exposure Weight MeasurementLocal Exposure WeightGlobal Exposure WeightJND-Base…

基于主动视觉机制的深度学习--一个综合池化框架

卷积神经网络(CNN)是深度学习的代表算法之一,长期以来被广泛应用于图像识别领域。它是受到了生物处理过程的启发,通过模仿人类视觉系统(HVS)的工作机制,完成各种视觉任务等。但与HVS相比,CNN不能够像人类一样,迅速的分…

第13章:直方图处理

第13章:直方图处理 一、直方图的含义:1. 普通直方图:2. 归一化直方图: 二、绘制直方图:1. 使用Numpy绘制直方图:2. 使用OpenCV绘制直方图:3. 使用掩码绘制直方图: 三、直方图均衡化&…

通过matlab,基于DCT变换,利用hvs实现水印嵌入强度自适应

我真的会谢,为什么我跑出来是一片黑呀?本matlab小白跪求matlab大佬答疑解惑555555感谢 以下是我的程序: % 读取原始图像和水印图像 I imread(lena.bmp); W imread(waterMark.bmp);% 将图像转为灰度图,并将水印调整为与原始图像…

基于HVS 的结构相似性的视频质量评价

清华大学的汪志兵, 廖煜鹏, 汪 博, 秦明海, 林行刚等人在《通信技术》2010年第2期上发表。   HVS 对不同频率分量的敏感性不同,对视频帧不同部分的关注度也不相同。 为了达到更好的效果,论文中引入3 个因…

一种基于HVS特性的视频质量评测方法

本篇论文是由厦门大学的袁飞,黄联芬,姚彦发表于《光电工程》2008年1月刊上。   本文针对视频质量的评测应用,通过在视频帧内图像和帧间图像的处理过程中引入人眼视觉系统(HVS)的主要特性,克服传统PSNR 算法在序列质量检测应用方…

数字水印算法matlab源程序 matlab版数字水印算法 /DCT/DWT/LSB/HVS/W-SVD数字水印源码 数字水印的嵌入和提取 W-SVD数字水印实现

发以下多套系统源码: 1、matlab版数字水印算法 2、MATLAB数字水印 源代码文档 3、数字水印技术matlab代码 4、数字水印 JPEG压缩 matlab代码 5、数字水印 添加噪声 matlab代码 6、各种数字水印的matlab源代码(有DFT,DCT,小波变换等…

基于hvs图像水印matlab和psnr nc的计算 首先读取图像和水印,进行图像加印

基于hvs图像水印matlab和psnr nc的计算 首先读取图像和水印,进行图像加印 然后进行攻击 攻击方式有白噪声,裁剪,旋转10度,压缩,和无攻击,然后最后还原水印。 ID:31314617581701451好好学习

opencv RGB2HVS

RGB色彩空间和HSV色彩空间的理解 本文的结构如下: 1、RGB色彩空间 2、HSV色彩空间(附HSV颜色分量范围表) 3、RGB到HSV的转换的Demo   使用OpenCV实现RGB转HSV,并通过滑动条动态设定HSV阈值   自己写程序,实现…

HVS颜色模型(六角锥体模型)

色调(H):用角度度量,取值范围为0~360,从红色开始按逆时针方向计算,红色为0,绿色为120,蓝色为240、他们的补色是:黄色为60,青色为180,紫色为300&am…

ISP——HVS

本片博文是一篇笔记,是在看论文的时候碰到下面一段话,反复把论文看了三遍才弄懂,刚开始老觉得和gamma的特性是反的,还一度怀疑论文些错了,经过反复琢磨才弄明白,故此写下笔记记录 Higher gap in intensity…