前置要求

安装Node.js

对应系统版本,下载并安装  Node.js (nodejs.org) 

更换Node.js源为国内镜像

查看当前源



npm config get registry



若源url为境外地址,更新为国内镜像



npm config set registry https://registry.npm.taobao.org/










安装Cypress

通过npm安装(Node.js的包管理工具)

1. 切换到项目根目录



cd /[项目根目录]



2. npm初始化

如果项目根目录下缺少 node_modules  文件夹或者  package.json  文件,需先执行npm初始化



npm init



3. 为该项目安装Cypress

 --save-dev 命令使Cypress作为dev dependency被安装,也可简写为 -D 



npm install cypress --save-dev



成功安装后项目根目录下会生成 node_modules 文件夹,并包含可执行文件 ./node_modules/.bin 

若遇到报错

The Cypress App could not be downloaded.

URL: https://download.cypress.io/desktop/10.1.0?platform=win32&arch=x64

Error: connect ETIMEDOUT 172.67.69.12:443

这个主要因为内网dhwifi网络做了屏蔽,则把网络切换为自己的移动wifi即可。

4. 权限设置

此步骤适用于VS Code,Powershell;若使用Git Bash终端或命令行(CommandLine),可跳过该步骤

查看当前命令终端权限



get-executionpolicy



如果显示为【限制】 Restricted ,则需要设置授权,执行



set-ExecutionPolicy RemoteSigned



之后再次查看权限,若显示为【远程签署】 RemoteSigned ,则表示授权成功








运行Cypress

启动命令

注意:若是对本地项目进行测试时,启动Cypress前需确保所在项目的网页APP已启动

方法1:完整命令



./node_modules/.bin/cypress open



方法2:快捷命令



$(npm bin)/cypress open



方法3:npx命令

注意:npx需要安装的npm版本 > 5.2



npx cypress open



安装Cypress执行文件

若启动命令时,遇到错误

 No version of Cypress is installed in: C:\..\Cypress\Cache\x.x.x\Cypress 

则需要手动安装Cypress执行文件



npx cypress install



而后,再使用启动命令



选择浏览器

成功启动Cypress后,会弹出Cypress的测试器窗口,如下。该测试器会自动识别该机器上与Cypress兼容的浏览器,并可通过右上角下拉式菜单选择。

测试器正下方【INTEGRATION TESTS】为测试示例,可以依次点击运行。












编写测试

添加测试文件

1. 位置

测试文件需要添加在项目文件夹下的 /cypress/integration/ 文件夹中,可以通过新建文件夹归档。

2. 类型

测试文件为JavaScript类型,例 samepleTest.js 。添加文件后,可以注意到在Cypress测试器中对应测试 samepleTest.js 的增加。





点击该测试查看细节(因为暂无测试用例,当前会显示找不到测试 No tests found. )。





3. 简单的测试

在 samepleTest.js 中添加如下内容并保存,以查看Cypress如何展示测试是否成功



describe('成功的测试', () => {
    it('TRUE==TRUE', () => {
        expect(true).to.equal(true)
    })
})
describe('失败的测试', () => {
    it('TRUE!=FALSE', () => {
        expect(true).to.equal(false)
    })
})



4. 实时反馈

在打开Cypress的测试器时,可以更改测试文件,保存后的更改内容会实时反馈在测试器中,以便调试。









测试构成

一般而言,测试由3个部分构成

1. Given

设定当前状态

2. When

执行某个操作

3. Then

断言状态变更



测试实例



describe('My First Test', () => {
    it('Gets, types and asserts', () => {
      // Given: 访问页面
      cy.visit('https://example.cypress.io')
      // When: 点击内容包含‘type’的元素
      cy.contains('type').click()
      // Then:获取URL,其中应包含‘/commands/actions’
      cy.url().should('include', '/commands/actions')

      // Given:找到class为‘action-email’的元素
      // When:输入‘fake@email.com’
      // Then:该元素的value应是‘fake@email.com’
      cy.get('.action-email')
        .type('fake@email.com')
        .should('have.value', 'fake@email.com')
    })
})



注意:

(1)Cypress使用链式语法

(2)单个测试 describe('测试',()=>{}) 中可以包含多个测试用例 it('测试用例',()=>{}) ;单个测试用例中可以包含多个平行的或顺序的断言 xxx.should() 

(3)可以通过链式语句增加状态、动作和断言

(4)当步骤涉及到页面加载时,Cypress会等待加载完毕才会继续执行后续步骤








调试代码

Cypress提供了一系列的debugging工具,以帮助理解测试。

1. 时间旅行

在Cypress测试器中,将鼠标移动到测试用例中任意行命令并悬停,Cypress会回溯到该命令执行时的状态,在右侧界面显示当时的页面(注意截图中的URL为页面跳转前的地址),高亮并置顶相关DOM组件。







2. 截图功能

在Cypress测试器中,单击任意行命令可以将其固定(以紫色高亮),这么做可以:





2.1 固定截图

当命令被固定后,鼠标移动到其他命令上时,右侧界面不会再变化。这样可以手动查看截图时页面的DOM元素。

2.2 事件触发

因为 .click() 是一个动作命令,该命令被固定时,可以观察到右侧界面的 type 处有红点显示(代表此处有事件触发)

2.3 截图菜单

当被锁定的命令是动作命令时(如截图中的 .type() ),右侧界面下方会出现额外的截图菜单,通过选择 before 或 after 来查看该动作命令执行前后的页面区别。

注意:如果动作命令涉及到页面加载(非瞬时操作),取决于该页面的加载速度,会导致选择 after 后可能看不到变化,或者只显示页面加载时的空白。







3. 报错信息

在测试中,当错误发生时,Cypress会提供以下信息:





3.1 错误名称

显示错误的类型,如 CypressError , AssertionError 

3.2 错误信息

显示错误的具体信息。有时还会提供修复办法。

3.3 了解更多 Learn more 

如果有此选项,点击此项可以打开相关的Cypress文档页面

3.4 代码文件

显示报错代码所在文件名、行数、字数。点击此项可以使用默认编辑器打开该文件,并高亮报错行(高亮需要编辑器支持)。

3.5 代码框

显示报错代码及上下文,并高亮报错代码行。

3.6 查看堆栈轨迹 View stack trace 

打开或关闭改错误堆栈轨迹的开关。

3.7 打印到控制台 Print to console 

点击此项可以把完整错误信息打印到DevTools的控制台中。



4. 页面事件

在Cypress测试器的左侧界面中,注意到有以下这样的日志——它们并不属于代码中的任何命令。这是因为CYpress会自动记录下测试中的重要页面事件。





Cypress会记录的页面事件有:

  • 网络XHR的请求

  • URL hash的变更

  • 页面的加载

  • 表单的提交



5. 控制台输出

Cypress可以在控制台中提供额外的调试信息。

打开浏览器的Dev Tools F12 ,并点击左侧界面中的 GET class选择器命令行。





可以看到Cypress提供的额外信息包括:

  •  Command :所触发的命令

  •  Yielded :命令返回的内容

  •  Elements :找到的元素数量

  •  Selector :所使用的参数

注意:若返回多个元素,可以在Dev Tools中展开以查看每个元素的信息。



6. 特殊命令

Cypess也提供了调试用的特殊命令,如 cy.pause() , cy.debug() 。

尝试在代码中加入 cy.pause() ,如下:



describe('My First Test', () => {
    it('Gets, types and asserts', () => {
      // Given: 访问页面
      cy.visit('https://example.cypress.io')

      // 调试:特殊命令
      cy.pause()

      // When: 点击内容包含‘type’的元素
      cy.contains('type').click()
      // Then:获取URL,其中应包含‘/commands/actions’
      cy.url().should('include', '/commands/actions')

      // Given:找到class为‘action-email’的元素
      // When:输入‘fake@email.com’
      // Then:该元素的value应是‘fake@email.com’
      cy.get('.action-email')
        .type('fake@email.com')
        .should('have.value', 'fake@email.com')
    })
})



如此,在Cypress测试器中,我们可以仿照debugger,在暂停处使用下一步 step forward 的调试功能












测试你的项目

第一步:启动你的服务器

注意:不要从Cypress脚本启动服务器。详情参考Cypress的最佳实践。



第二步:访问你的服务器

在测试文件夹 cypress/integration 下,新建你的测试脚本 xxx.js 



describe('应用首页', () => {
  it('加载成功', () => {
    cy.visit('http://localhost:8080') // URL替换为你的开发环境URL
  })
})



保存后在Cypress测试器中打开该测试 xxx.js 。若一切顺利,测试器中可以看到已访问对应URL的页面。



第三步:配置Cypress

考虑到每个测试都需要访问页面,Cypress提供了配置基础URL的方式:在配置文件中 cypress.json ,加上 baseUrl 的配置。



{
  "baseUrl": "http://localhost:8080"
}



如此,在测试中调用 cy.visit() 和 cy.request() 命令时,会自动使用配置URL作为前缀。

配置完成后,先前的 xxx.js 可以写成这样:



describe('应用首页', () => {
  it('加载成功', () => {
    cy.visit('/')
  })
})





测试策略

测试哪些方面,如何定义测试用例的边界值,如何做回归测试,等等,完全取决于你自己、你的应用和你的团队,请自由发挥。



种子数据

最常用的3个准备命令:

  •  cy.exec() :用以执行系统指令

  •  cy.task() :在Node中通过 pluginsFile 来执行命令

  •  cy.request() :发出HTTP请求

例如,如果机器上装有 node.js ,那么可以在 before 或者 beforeEach 钩子代码中执行 npm 任务。



describe('应用首页', () => {
  beforeEach(() => {
    // 重置数据库并使用种子数据
    cy.exec('npm run db:reset && npm run db:seed')
  })
  it('加载成功', () => {
    cy.visit('/')
  })
})





绕过服务器(Mock)

除了使用种子数据,Cypress也支持仿造返回的JSON,这与Mock相似。这么一来,不仅避免了数据从服务器到浏览器的同步等待时间,也避免了测试时的状态转变。这也意味着一个测试不会生成影响其他测试的状态。

此外,通过这种方法,可以完全无需后台服务器就建立一套完整的测试,并赋予想要准备的数据。

尽管如此,以上两种策略之间应该有个平衡点,需要自己去探索。

另一方面,使用Mock的话没办法保证仿造的数据与服务器的真实返回一致。幸运的是,Cypress提供了一些方法可以解决这个问题。

1. 基境数据

可以预先通过服务器生成的真实数据,并存为基境数据,用以Mock

2. E2E测试+Mock测试

这是一种更平衡的策略。可以先完成一个无Mock的端到端测试,再通过Mock去完成所有的边界测试和特殊情景测试。这样既保证了测试的真实性,同时也兼顾了测试用例的便捷性和完成速度。



登录测试

登录测试往往是你的应用里第一个(甚至是最难的之一)需要征服的测试。基于上一部分的两种策略,可以在Cypress中这样实现:

1. 完整的登录流程只测试一次

因为登录是最重要的功能之一,并且涉及到与服务器的交互,所以这里推荐使用UI交互的方式去测试。

以下是一段代码示例,包含了种子数据策略:



describe('登录页面', () => {
  beforeEach(() => {
    // 重置数据库并使用种子数据
    cy.exec('npm run db:reset && npm run db:seed')
    // 为接下来的测试创建一个种子账号
    // 假设它同时会生产一个随机密码
    cy.request('POST', '/test/seed/user', { username: 'jane.lane' })
      .its('body')
      .as('currentUser')
  })
  it('通过登录页面登录并设置权限cookie', function () {
    // 从this.currentUser中解构出username和password
    const { username, password } = this.currentUser
    cy.visit('/login')
    // 从name=username的输入框输入刚刚获得的username
    cy.get('input[name=username]').type(username)
    // 从name=password的输入框输入刚刚获得的password
    // {enter}模拟回车触发登录请求
    cy.get('input[name=password]').type(`${password}{enter}`)
    // 成功登录后,URL应当包含dashboard()
    cy.url().should('include', '/dashboard')
    // 权限cookie应当存在
    cy.getCookie('your-session-cookie').should('exist')
    // UI界面应当反映登录的用户名
    cy.get('h1').should('contain', 'jane.lane')
  })
})



类似的,完整的UI测试还可以覆盖如下:

  • 用户名/密码为空

  • 用户名/密码不正确

  • 注册时用户名已存在

  • 注册时密码强度不符合要求

  • 特殊情况如账号被锁/被删除



2. 其他相关的测试使用Mock

当需要继续进行其他依赖于登录状态的测试时,则推绕开UI登录的方法。Cypress提供了 cy.request() 指令,它可以自动获取和设置cookies。我们可以通过这个指令来构建和通过UI登录完全一致的登录状态,而不需要借助UI。

示例代码如下:



describe('Dashboard页面', () => {
  beforeEach(() => {
    // 重置数据库并使用种子数据
    cy.exec('npm run db:reset && npm run db:seed')
    // 创建一个种子账号
    // 假设它同时会生产一个随机密码
    cy.request('POST', '/test/seed/user', { username: 'jane.lane' })
      .its('body')
      .as('currentUser')
  })
  it('绕过UI,自动登录', function () {
    // 从this.currentUser中解构出username和password
    const { username, password } = this.currentUser
    // 通过POST请求自动登录,从而绕过UI
    cy.request('POST', '/login', {
      username,
      password,
    })
    // 现在已经是登录状态
    // 可以不受限制地访问任何页面了
    cy.visit('/dashboard')
    // 权限cookie应当存在
    cy.getCookie('your-session-cookie').should('exist')
    // UI界面应当反映登录的用户名
    cy.get('h1').should('contain', 'jane.lane')
  })
})



通过绕过UI的方法,对于后续的每个测试,我们都节约了大量的时间(加载登录页面,从UI输入用户名、密码再登录)。并且因为此前已经完整地测试过登录的流程,所以我们有十足的把握来用这一快捷方式。



一言以蔽之:

  • 当需要测试特定功能时,应当用完整的UI测试

  • 当需要准备某一状态(基境)且这个状态已经被完整测试过时,准备的过程可以通过绕过UI的方式来实现



开始你的测试

关于Cypress的介绍已经步入尾声。从现在起,开始为你的应用测试吧!








附录

Cypress官方文档

 Why Cypress? | Cypress Documentation 



ESLint插件

 GitHub - cypress-io/eslint-plugin-cypress: An ESLint plugin for projects that use Cypress

Cypress使用教程相关推荐

  1. cypress自动化测试工具开发指南

    待到秋来九月八,我花开后百花杀 简介 cypress安装教程(MacOS版本) 安装前准备 安装方式 安装后使用 cucumber插件安装 cypress的基础配置 插件支持配置--package.j ...

  2. Cypress简易入门教程

    1 Windows下安装 1.1方法一 1)安装node.js(https://nodejs.org/en/download/),根据版本选择32位或64位. 2)确认ndejs和npm是否安装上: ...

  3. Cypress 前端 E2E 测试——手把手入门教程

    目录 初始化项目 准备好 Docker 镜像 安装依赖 ESLint 配置 IDE 集成 配置 手动配置 Gitlab 集成 测试用例 配置环境变量 静态变量 动态变量 使用变量 添加 Command ...

  4. e2e测试框架之Cypress

    谈起web自动化测试,大家首先想到的是Selenium!随着近几年前端技术的发展,出现了不少前端测试框架,这些测试框架大多并不依赖于Selenium,这一点跟后端测试框架有很大不同,如Robot Fr ...

  5. 「伯克利大学」 的计算机入门教程

    每天给你推荐一个新奇,好玩,高品质的开源库,好文,观点或言论等. ❝ 项目主页维护当前月份的内容,想看往期内容,可以翻到下方历史汇总部分,然后选择自己感兴趣的月份点进去即可. ❞ 2022-04 20 ...

  6. (原创)LEON3入门教程(三):基于LEON3的SOPC设计以及HELLOWORLD和流水灯

    摘要:通过前两篇博客的介绍,Windows下基本的LEON3开发环境就已经搭建好了.这篇博客将要介绍LEON3 SOPC平台的搭建(使用Cygwin+GRLIB)和 LEON3 IDE(eclipse ...

  7. Cypress入门-(一)如何安装Cypress

    Cypress介绍和原理之类的就不说了,自己查查都能查到,直接上干货-安装教程 一.下载安装node.js 1.下载地址:https://nodejs.org/en/ 电脑是win10的话一般都下载最 ...

  8. 前端 react教程(详细版)

    1. React概述 1.1 React是什么 React是一个用于构建用户界面的JavaScript库. React的主要特点是组件化.声明式编程以及高效的DOM更新机制. React由Facebo ...

  9. 涂鸦蓝牙SDK开发系列教程——1.快速入门

    本系列课程将介绍如何使用 涂鸦蓝牙模组及其 SDK 进行产品开发,帮助开发者更快掌握 涂鸦蓝牙模组.涂鸦蓝牙 SDK.涂鸦 IoT 平台.涂鸦三明治开发套件.涂鸦云模组烧录授权平台 等开发工具的使用方 ...

  10. 种草Cypress和TestCafe,QA同学一定想了解的Web UI自动化测试工具

    摘要:Cypress和TestCafe这两个工具相比于Selenium都更加的轻量级,且在不同的方面有了改进,比如安装更简单,增加了内置等待机制,调试更加方便等. Cypress.TestCafe.P ...

最新文章

  1. 2019年9月全国程序员工资统计。
  2. 清华大学、中科院等研究机构研究人员提出BETA:面向SSVEP-BCI应用程序的大型基准测试数据库...
  3. C++TSL之map容器(悲伤的故事)
  4. CWDM/DWDM是城域网最好的选择吗?
  5. Elasticsearch之mapping映射入门
  6. Java——集合带All的功能演示
  7. Python学习笔记:安装OBSFTP时出现的版本异常问题
  8. 改变select组件的option选中状态的快捷方法
  9. python模块导入与使用
  10. 什么是次梯度(次导数)
  11. SpringBoot2.x炫酷吊炸天前后端分离的后台管理系统实例
  12. Android Studio .jar 包的引用方式(导入方式)
  13. python:使用split以.划分句子、对列表进行切片
  14. 浏览器图标及名称大全_估计真要卸载谷歌浏览器了!自带黑科技浏览器推荐(下)...
  15. Vue安装必要插件element-ui插件及axios依赖(详细)
  16. uniapp-连接服务器超时,点击重试
  17. eclipse 中使用@slf4j报log找不到
  18. phpmywind教程:单页信息调用说明【进阶篇一】
  19. Java中的十大组织
  20. 微信扫码---进入小程序指定页面(传参)

热门文章

  1. SSM基于web的教务管理系统 毕业设计-附源码261620
  2. 解决IE上登陆oracle OEM时报:“证书错误,导航已阻止”且无继续浏览的错误
  3. Linux设置root权限
  4. 【MyBatis】框架-----MyBatis的基础知识以及案例分析
  5. 抖音小程序开发教程之 01 构建开发环境(教程含源码)
  6. html几种美丽的分割线
  7. AD单片机九齐单片机NY8B062D SOP16九齐
  8. 电脑永不关机(Windows10)
  9. 计算机没有autoCAD_《AutoCAD三维设计环境》
  10. 成功学大师枭哥搞砸了,听懂掌声!