0

0

掌握Cypress异步命令与状态管理:解决测试中的执行顺序问题

霞舞

霞舞

发布时间:2025-10-17 08:32:11

|

360人浏览过

|

来源于php中文网

原创

掌握Cypress异步命令与状态管理:解决测试中的执行顺序问题

本文深入探讨了在cypress测试中常见的javascript异步执行和命令队列问题,特别是在处理动态数据时变量值错乱的现象。文章详细解释了cypress命令的异步性质,并提供了两种核心解决方案:利用`cy.then()`确保命令的顺序执行,以及使用`cypress.env()`在页面刷新或测试步骤间持久化数据,从而构建更稳定、可靠的自动化测试。

在Cypress自动化测试中,开发者经常会遇到一个挑战:从UI中提取数据并在后续步骤中使用时,变量的值并非预期。这通常是由于对Cypress命令的异步性质和JavaScript的同步执行机制理解不足导致的。

理解Cypress命令队列与JavaScript同步执行

Cypress测试的核心在于其“命令队列”机制。当您编写cy.get(), cy.invoke(), cy.then()等Cypress命令时,这些命令并不会立即执行,而是被添加到一个内部队列中。Cypress会按照队列顺序逐一执行这些命令。然而,普通的JavaScript代码(例如变量赋值、console.log()等)是同步执行的,它们会立即运行,而不会等待Cypress队列中的命令完成。

考虑以下示例代码,它试图从页面中提取一个数字并存储到count变量中,然后在后续步骤中使用:

const MATCHING_MESSAGE = '[data-cy=matchingMessages]';
let count = 0;

// 这段代码将Cypress命令添加到队列中
cy.get(MATCHING_MESSAGE)
  .invoke('text')
  .then((text) => {
    const pattern = /[0-9]+/g;
    count = text.match(pattern).pop(); // count在此处被赋值
    console.log({count1: count}); // 此时count为正确的值,但执行晚于下面的同步代码
  });

// 模拟跳转到下一页的操作
// cy.visit('/next-page');

// 这段JavaScript代码是同步执行的,会立即运行
console.log({count2: count}); // 此时count仍为初始值0,因为上面的Cypress命令尚未执行
if (count > 0) {
  // 使用count进行操作
} else {
  // 使用默认值
}

执行上述代码时,控制台输出可能会是:

log: count2: 0
log: count1: 3234

这清楚地表明,console.log({count2: count})在count被Cypress命令赋值之前就已经执行了,导致count的值仍然是其初始值0。这是典型的异步执行顺序问题。

解决方案一:利用cy.then()确保执行顺序

要解决这个问题,关键在于将依赖于Cypress命令结果的JavaScript逻辑也纳入Cypress的命令队列中。cy.then()命令正是为此目的而设计。它确保其回调函数在之前的Cypress命令完成后才执行。

以下是使用cy.then()修正后的代码:

const MATCHING_MESSAGE = '[data-cy=matchingMessages]';
let count = null; // 初始化为null更清晰,避免与0混淆

// Cypress命令队列
cy.get(MATCHING_MESSAGE)
  .invoke('text')
  .then((text) => {
    const pattern = /[0-9]+/g;
    count = text.match(pattern).pop();
    console.log({count1: count}); // 此时count已获得正确值
  });

// 模拟跳转到下一页的操作
// cy.visit('/next-page');

// 使用cy.then()将后续逻辑也加入Cypress队列
cy.then(() => {
  // 这段代码会在前面的Cypress命令(包括对count的赋值)执行完成后才运行
  console.log({count2: count}); // 此时count将是正确的值

  // 注意:从文本提取的数字通常是字符串,进行数值比较前最好转换
  if (parseInt(count) > 0) {
    // 使用count进行操作,例如:
    // cy.get('input[name="target-field"]').type(count);
  } else {
    // 使用默认值
    // cy.get('input[name="target-field"]').type('5');
  }
});

通过将依赖count值的逻辑封装在cy.then()的回调中,我们确保了这些逻辑在count变量被正确赋值之后才执行,从而解决了执行顺序问题。

解决方案二:使用Cypress.env()处理页面刷新和状态持久化

上述cy.then()的解决方案适用于在同一页面或不引起页面刷新的操作中传递数据。然而,如果测试步骤中包含页面刷新(例如cy.visit()到新页面,或点击导致页面重载的链接),那么之前通过let count = ...声明的JavaScript变量将会被重置,因为它们是当前页面上下文的一部分。

在这种情况下,我们需要一个机制来在Cypress测试的不同阶段(甚至跨页面刷新)持久化数据。Cypress.env()提供了一个全局的环境变量存储,可以在整个测试运行期间保持数据。

以下是使用Cypress.env()修正后的代码:

const MATCHING_MESSAGE = '[data-cy=matchingMessages]';

cy.get(MATCHING_MESSAGE)
  .invoke('text')
  .then((text) => {
    const pattern = /[0-9]+/g;
    const extractedCount = text.match(pattern).pop();
    console.log({count1: extractedCount});
    // 将提取到的值存储到Cypress环境中
    Cypress.env('extractedCount', extractedCount);
  });

// 模拟跳转到下一页的操作,这可能导致页面刷新
// cy.visit('/next-page');

cy.then(() => {
  // 从Cypress环境中恢复值
  const count = Cypress.env('extractedCount');
  console.log({count2: count});

  if (parseInt(count) > 0) {
    // 使用count进行操作
    // cy.get('input[name="target-field"]').type(count);
  } else {
    // 使用默认值
    // cy.get('input[name="target-field"]').type('5');
  }
});

通过Cypress.env('key', value)存储数据,以及Cypress.env('key')检索数据,即使页面发生刷新,我们也能确保数据的持久性。这对于在复杂的测试流程中传递状态信息至关重要。

总结与最佳实践

  1. 理解Cypress命令的异步性: Cypress命令被添加到队列中异步执行,而普通JavaScript代码是同步执行的。
  2. 利用cy.then()控制执行顺序: 当您的JavaScript逻辑依赖于Cypress命令的结果时,务必将其封装在cy.then()的回调函数中,以确保正确的执行顺序。
  3. 使用Cypress.env()进行状态持久化: 如果测试步骤中涉及页面刷新,或者需要在多个测试文件/步骤之间共享数据,请使用Cypress.env()来存储和检索数据,确保数据不会丢失。
  4. 数据类型转换: 从UI中提取的文本通常是字符串。在进行数值比较或数学运算之前,请使用parseInt()或parseFloat()进行适当的类型转换。
  5. 初始化变量: 为了避免混淆,建议将可能被异步赋值的变量初始化为null而不是0,这样在调试时可以清楚地判断变量是否已被赋值。

通过深入理解Cypress的异步执行机制并恰当运用cy.then()和Cypress.env(),您可以编写出更加健壮、可靠且易于维护的自动化测试脚本。

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

通义千问
通义千问

阿里巴巴推出的全能AI助手

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
数据类型有哪几种
数据类型有哪几种

数据类型有整型、浮点型、字符型、字符串型、布尔型、数组、结构体和枚举等。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

309

2023.10.31

php数据类型
php数据类型

本专题整合了php数据类型相关内容,阅读专题下面的文章了解更多详细内容。

222

2025.10.31

c语言中null和NULL的区别
c语言中null和NULL的区别

c语言中null和NULL的区别是:null是C语言中的一个宏定义,通常用来表示一个空指针,可以用于初始化指针变量,或者在条件语句中判断指针是否为空;NULL是C语言中的一个预定义常量,通常用来表示一个空值,用于表示一个空的指针、空的指针数组或者空的结构体指针。

235

2023.09.22

java中null的用法
java中null的用法

在Java中,null表示一个引用类型的变量不指向任何对象。可以将null赋值给任何引用类型的变量,包括类、接口、数组、字符串等。想了解更多null的相关内容,可以阅读本专题下面的文章。

438

2024.03.01

counta和count的区别
counta和count的区别

Count函数用于计算指定范围内数字的个数,而CountA函数用于计算指定范围内非空单元格的个数。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

198

2023.11.20

js 字符串转数组
js 字符串转数组

js字符串转数组的方法:1、使用“split()”方法;2、使用“Array.from()”方法;3、使用for循环遍历;4、使用“Array.split()”方法。本专题为大家提供js字符串转数组的相关的文章、下载、课程内容,供大家免费下载体验。

298

2023.08.03

js截取字符串的方法
js截取字符串的方法

js截取字符串的方法有substring()方法、substr()方法、slice()方法、split()方法和slice()方法。本专题为大家提供字符串相关的文章、下载、课程内容,供大家免费下载体验。

212

2023.09.04

java基础知识汇总
java基础知识汇总

java基础知识有Java的历史和特点、Java的开发环境、Java的基本数据类型、变量和常量、运算符和表达式、控制语句、数组和字符串等等知识点。想要知道更多关于java基础知识的朋友,请阅读本专题下面的的有关文章,欢迎大家来php中文网学习。

1499

2023.10.24

Python 自然语言处理(NLP)基础与实战
Python 自然语言处理(NLP)基础与实战

本专题系统讲解 Python 在自然语言处理(NLP)领域的基础方法与实战应用,涵盖文本预处理(分词、去停用词)、词性标注、命名实体识别、关键词提取、情感分析,以及常用 NLP 库(NLTK、spaCy)的核心用法。通过真实文本案例,帮助学习者掌握 使用 Python 进行文本分析与语言数据处理的完整流程,适用于内容分析、舆情监测与智能文本应用场景。

10

2026.01.27

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
React 教程
React 教程

共58课时 | 4.2万人学习

TypeScript 教程
TypeScript 教程

共19课时 | 2.5万人学习

Bootstrap 5教程
Bootstrap 5教程

共46课时 | 3万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号