cypress 教程

cypress是一个用于Web应用程序的端到端测试框架。它是一个开源的js测试工具,设计的目的是Web应用程序的测试能更快速、简单和可靠。赛普斯允许开发人员编写模拟用户交互和验证应用程序行为的自动测试。

我们可以使用js或者ts来开发,但是jscypress的主要语言。cypress是建立在js之上的,使用了许多现代Web开发的相同概念,比如使用基于浏览器的环境来运行测试,以及使用CSS选择器与Web元素进行交互。

在编写cypress测试时,我们可以使用js创建模拟用户交互和验证应用程序行为的测试用例。cypress还提供了一套强大的内置命令和断言,以帮助我们快速和方便地编写测试。

在详细解释cypress之前,我们先来看看为什么我们要使用cypress来实现测试用例的自动化。

为什么要使用cypress

通过js编写

cypress是用js编写的,对于我们已经熟悉js的开发人员来说能更容易上手cypress

对js框架提供了支持

cypressvuereact提供了很好的支持。使用这些框架构建应用程序的开发人员可以很容易地为他们的应用程序编写测试。

拥有丰富的与Web应用程序交互的API

提供丰富的与Web应用程序进行交互的API,其中包括与DOM进行交互的方法、HTTP请求和处理事件。这些API设计得很容易使用,并且拥有详细的文档介绍,这使得使用js编写测试变得很容易。

支持 debugger

提供全面的调试体验,包括内置的调试工具和通过测试的能力。

社区支持

有一个庞大的js开发者社区,意味着大量的资源可以在网上帮助开发者解决他们在使用cypress时遇到的任何问题。

cypress使用一个独特的体系结构,使其能够在与被测试的应用程序相同的上下文中运行测试。这意味着cypress可以访问应用程序的DOM、网络流量,甚至是后端服务器。这种架构允许更快和更可靠的测试和更直观和强大的测试经验。

使用cypress的好处

cypress能使编写和运行测试、调试问题变得容易,并确保了Web应用程序的质量。下面我们将探讨cypress自动化工具的一些主要特点。

简单的设置

cypress是非常容易建立和使用。它可以很容易地安装在国家预防机制中,只需要很少的设置。cypress还配有一个方便用户的图形界面,使开发人员易于导航和使用。

全面 APIS

提供丰富的与Web应用程序进行交互的API,其中包括与DOM进行交互的方法、HTTP请求和处理事件。这些API设计得很容易使用,并且拥有详细的文档介绍,这使得使用js编写测试变得很容易。

实时重载

提供实时的重新加载,这意味着对代码或测试的任何更改都能立即反映在浏览器中。这样可以节省开发人员的时间,使实时查看变化的影响变得容易。

自动等候

在执行下一个命令之前,赛普雷斯JavaSoript会自动等待断言传递和元素显示。这使测试更加稳定,并减少了错误底片的可能性。

调试

配备了内置的调试工具,使故障诊断和修复测试变得容易。开发人员可以使用这些工具来检查DOM、调试javaSoript代码等。

时间旅行

提供了一个独特的特性,叫做"时间旅行",它允许我们在测试的任何点上来回地检查和调试应用程序。当试图调试复杂的测试场景时,这个功能可以节省开发人员大量的时间和精力。

跨浏览器测试

支持跨浏览器测试,并可以在不同的浏览器上运行测试。这使得我们可以很容易地确保您的应用程序在不同的浏览器中工作。

自动截图和录像

可以自动拍摄测试的截图和视频,这样就可以很容易地看到测试运行过程中发生了什么。这在试图识别应用程序中的问题或错误时会很有帮助。

定制命令

允许开发人员创建自定义命令,这些命令可以在不同的测试中重用。这使得创建一个通用测试命令库和减少代码重复的数量变得容易。

持续整合

可以很容易地集成到流行的连续集成(CI)工具,如Jenkins, CircleCITravis CI.。这使得作为CI/CD管道的一部分自动运行测试变得容易。

cypress的使用

安装nodejs

需要有nodejs环境,可以在https://nodejs.org/下载。

创建一个项目

创建一个新目录,并在根目录下通过npm init来生成package.json文件

安装 cypress

在根目录下执行

npm install cypress --save-dev

yarn add cypress --dev

打开cypress

npx cypress open

可以看到支持端到端测试和组件测试这两种:

  • 端到端测试:从端到端构建和测试应用程序的整个体验,以确保每个流符合我们的期望。
  • 组件测试:独立地从设计系统构建和测试组件,以确保每个状态符合我们的期望。

cypress如何录制案例 cypress教程_ecmascript

这两种测试存在一定的区别:

端到端测试通过 cy.visit() 访问网站,可以跨多个页面测试流程和功能。而组件测试通过 cy.mount() 导入组件,主要用于隔离测试设计系统的各个组件。

cypress如何录制案例 cypress教程_cypress如何录制案例_02

端到端测试生成一个空白规范:

cypress如何录制案例 cypress教程_前端_03

选择浏览器,在这里我们选择Edge,然后启动端到端测试:

cypress如何录制案例 cypress教程_javascript_04

cypress如何录制案例 cypress教程_ecmascript_05

创建一个空白测试用例:

cypress如何录制案例 cypress教程_cypress如何录制案例_06

创建完后运行:

cypress如何录制案例 cypress教程_前端_07

在创建了测试用例后,可以在项目根目录上看到多了一个cypress文件夹,默认文件夹结构如下所示。我们可以在文件夹e2e下创建测试用例。

cypress如何录制案例 cypress教程_应用程序_08

cypress的项目结构
  • cypress:这是 cypress 项目的主文件夹(也就是执行run cypress open命令后生成的)。它包含与我们的测试相关的所有子文件夹和文件。
  • e2e:这是存储所有测试的主文件夹。我们可以在此处添加基本、端到端测试。所有的spec文件都在这个文件夹里边。
  • fixtures:这个文件夹可以用于存储测试中使用到的静态数据文件,例如 JSONCSV 文件。例如,包含多个测试用例可以使用的测试数据列表。
  • support: 此文件夹包含可在多个测试文件之间共享的可重用测试代码。可以包括自定义命令、页面对象或函数。

support 文件夹中有两个文件:commands.jsindex.js

  • command.js:用于放置常用函数和自定义命令。包括在不同测试文件中使用到的常用函数。Cypress 为也我们创建了一些函数,如果有特殊需求,也可以在此处重写它们。
  • e2e.js:这个文件在每个测试文件之前运行。在此文件中,我们保留所有全局配置,并可以根据需要进行修改。默认情况下,它仅导入 commands.js,但是我们也可以导入或要求其他文件。
  • node_modules:所有节点包将安装在node_modules目录中,并在所有测试文件中可用。简而言之,这是 NPM 安装所有项目依赖项的文件夹。
  • cypress.config.js:这是 cypress 框架使用的配置文件,用于自定义框架和测试的行为。该文件可用于配置测试的各种设置,例如应用程序的基本 URL、视口大小、测试超时值和其他选项。

除了上述文件夹外,我们还有一些文件夹,例如“屏幕截图”、“下载”和“视频”来存储不同的相关文件。

cypress 的基本结构

cypress 使用与 Mocha 相同的语法来编写测试用例:

  • describe(): 该方法用于对相关测试用例进行分组。它需要两个参数:一个描述测试用例组的字符串和一个包含各个测试用例的回调函数。
  • it(): 该方法用于定义测试用例。它需要两个参数:一个描述测试用例的字符串和一个包含实际测试代码的回调函数。一个describe()至少要包含一条测试用例:it().
  • before():此方法用于在特定描述的块中的任何测试用例之前运行设置函数。可用于设置测试环境、初始化变量以及执行其他设置任务。
  • after(): 此方法用于在特定描述的块中的所有测试用例完成运行后运行清理功能。它可用于清理测试环境、关闭打开的连接以及执行其他清理任务。
  • beforeEach(): 此方法用于在特定描述的块中的每个测试用例之前运行设置函数。它可用于重置测试环境的状态并执行其他设置任务。
  • afterEach(): 此方法用于在特定描述的块中的每个测试用例完成运行后运行清理功能。它可用于重置测试环境的状态并执行其他清理任务。
  • .skip(): 当处理大型代码库并希望专注于特定测试或测试子集时,.skip() 函数提供了一种方便的方法来暂时阻止某些测试的执行。

测试应用下载

我们使用Cypress.io的官方提供的测试应用来做介绍,就不单独写应用了。

github上复制项目

git clone git@github.com:cypress-io/cypress-example-recipes.git

之后在根目录下安装依赖:

npm install

cypress如何录制案例 cypress教程_ecmascript_09

所有应用例子都在项目的examples文件夹下。

启动测试应用

进入想要测试的应用的目录。

我们这里以登录应用为例(logging-in__xhr-web-forms目录).

进入该应用的目录:

cd examples\logging-in__xhr-web-forms

启动服务:

npm start

启动成功后,cmd窗口将显示服务器的地址和端口

cypress如何录制案例 cypress教程_前端_10

在浏览器中访问:

cypress如何录制案例 cypress教程_cypress如何录制案例_11

进行 UI 测试

cypress 提供对应用程序 DOM 的轻松访问,从而可以轻松操作和断言页面上各个元素的状态。它还支持插件,可用于扩展其功能并与其他工具和服务集成。这些是 cypress 成为 UI 测试首选的原因。

测试用例

在之前创建的空白测试文件中进行修改:

describe('login', () => {
  const username = 'jane.lane';
  const password = 'password123';
  it('login ', () => {
    cy.visit('http://localhost:7079/login');
    cy.get('input[name=username]').type(username);
    cy.get('input[name=password]').type(password);
    cy.get('form').submit();

    cy.url().should('include', '/dashboard');
    cy.get('h1').should('contain', 'jane.lane');
  });
});

cypress如何录制案例 cypress教程_cypress如何录制案例_12

进行 API 测试

可以创建将 HTTP 请求发送到其应用程序的 API 并验证相应响应的测试。

这种类型的测试对于测试 API 响应、验证数据输入和输出以及验证应用程序的行为特别有用。它还提供了几个内置断言,可用于验证响应状态代码、标头和正文。

以下是使用 Cypress 进行 API 测试的一些关键功能:

  • HTTP 请求
  • cypress 提供了简单直观的 API 来发出 HTTP 请求,允许开发人员轻松测试不同的 API 端点和参数。它支持所有常见的HTTP方法,例如GETPOSTPUTDELETE等。
  • mockcypress 允许您模拟 API 响应,这在测试依赖于第三方服务或数据源的 API 端点时非常有用,这些服务或数据源在开发/测试期间可能不可用。
  • 请求和响应对象
    cypress 提供请求和响应对象,允许开发人员检查和操作 API 发送和接收的数据。这有助于测试具有嵌套数据结构的复杂 API
  • 身份验证和授权
    cypress支持测试需要身份验证或授权的 API。测试人员可以使用内置的 cy.request 方法来发送身份验证令牌或 cookie,也可以使用插件与外部服务(如 OAuth 提供程序)集成。
  • 内置对 GraphQL 的支持
  • cypress 为测试 GraphQL API 提供了内置支持,包括简化 GraphQL 查询的 GraphQL 请求方法。
测试用例

GET请求

GET 方法用于检索特定数据,并在从 API 响应读取代码时传递参数。

describe('login', () => {
  it('is redirected using cy.request', function () {
    cy.request({
      url: 'http://localhost:7077/dashboard',
      followRedirect: false,
    }).then((resp) => {
      expect(resp.status).to.eq(302);
      expect(resp.redirectedToUrl).to.eq('http://localhost:7077/unauthorized');
    });
  });
});

cypress如何录制案例 cypress教程_ecmascript_13

POST请求
POST 请求中,我们通过在body中传递数据。

describe('login', () => {
  const username = 'jane.lane';
  const password = 'password123';

  it('test login', function () {
    cy.request({
      method: 'POST',
      url: 'http://localhost:7077/login',
      form: true,
      body: {
        username,
        password,
      },
    });
    cy.getCookie('cypress-session-cookie').should('exist');
  });
});

cypress如何录制案例 cypress教程_javascript_14

其他请求方式类似,就不一一列举了。

进行组件测试

组件测试的目的是验证各个软件模块(如函数、类或方法)的功能和行为,以确保它们按预期工作并满足设计中指定的要求。

组件测试的主要目的是在软件模块集成到更广泛的系统之前发现软件模块中的缺陷或故障,从而最大限度地减少下游故障的可能性,并简化隔离和解决问题的过程。

通过隔离测试每个组件,开发人员可以确信每个模块都正常工作,这可以提高整体系统质量并减少测试和调试的时间和成本。

测试用例

这里以react为例:

# 创建一个项目:
create-react-app my-new-sample-app

# 在项目中安装cypress
npm i cypress -D

# 打开cypress
npx cypress open

之后选择组件测试

cypress如何录制案例 cypress教程_ecmascript_15

选择react框架

cypress如何录制案例 cypress教程_ecmascript_16

安装所有依赖项:

cypress如何录制案例 cypress教程_前端_17

之后的流程跟之前提到的一样,选择浏览器跟创建空白测试规范。

最终创建的文件夹:

cypress如何录制案例 cypress教程_javascript_18

src 文件夹中创建一个“计数器组件”,并命名为 lambadaTest.jsx。

import { useState } from 'react'

export default function Counter({ initial = 0 }) {
   const [count, setCount] = useState(initial)
   return (
       <div style={{
           padding: 30
       }}>
           <button style={{ color: "black", backgroundColor: "green", margin: 10 }} aria-label="decrement" onClick={() => setCount(count - 1)}>
               -
           </button>
           <span data-cy="counter">{count}</span>
           <button style={{ color: "black", backgroundColor: "green", margin: 10 }} aria-label="increment" onClick={() => setCount(count + 1)}>
               +
           </button>
       </div>
   )
}

执行下面的命令来运行测试用例:

npx cypress open --component

可以看到组件测试已执行

cypress如何录制案例 cypress教程_前端_19

编写用例:

  • 单击 (+) 以增加计数。
  • 单击 (-) 以递减计数。
import Counter from '../../src/lambadaTest'
describe("<Counter>", () => {
 const counterSelector = '[data-cy="counter"]';
 const incrementSelector = "[aria-label=increment]";
 const decrementSelector = "[aria-label=decrement]";
 it("Do two time increment then one time decrement the count ", () => {

   cy.mount(<Counter />);
   // 增加两次
   cy.get(incrementSelector).click();
   cy.get(incrementSelector).click();
   cy.get(counterSelector).should("contain.text", 2);

   // 递减
   cy.get(decrementSelector).click();
   cy.get(counterSelector).should("have.text", "1");
   cy.get(decrementSelector)
     .should("have.css", "color")
     .and("eq", "rgb(0, 0, 0)");
   cy.get(decrementSelector)
     .should("have.css", "background-color")
     .and("eq", "rgb(0, 128, 0)");
 });
 it("Do two time decrement then one time increment the count ", () => {

   cy.mount(<Counter />);
   cy.get(decrementSelector).click();
   cy.get(decrementSelector).click();
   cy.get(counterSelector).should("have.text", "-2");

   cy.get(incrementSelector).click();
   cy.get(counterSelector).should("have.text", "-1");
   cy.get(decrementSelector)
     .should("have.css", "color")
     .and("eq", "rgb(0, 0, 0)");
   cy.get(decrementSelector)
     .should("have.css", "background-color")
     .and("eq", "rgb(0, 128, 0)");
 });
});

将计数递增两次,然后递减一次计数。

cypress如何录制案例 cypress教程_应用程序_20

将计数递减两次,然后递增一次计数。

cypress如何录制案例 cypress教程_前端_21