
本文深入探讨了在cypress测试中常见的javascript异步执行和命令队列问题,特别是在处理动态数据时变量值错乱的现象。文章详细解释了cypress命令的异步性质,并提供了两种核心解决方案:利用`cy.then()`确保命令的顺序执行,以及使用`cypress.env()`在页面刷新或测试步骤间持久化数据,从而构建更稳定、可靠的自动化测试。
在Cypress自动化测试中,开发者经常会遇到一个挑战:从UI中提取数据并在后续步骤中使用时,变量的值并非预期。这通常是由于对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。这是典型的异步执行顺序问题。
要解决这个问题,关键在于将依赖于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变量被正确赋值之后才执行,从而解决了执行顺序问题。
上述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')检索数据,即使页面发生刷新,我们也能确保数据的持久性。这对于在复杂的测试流程中传递状态信息至关重要。
通过深入理解Cypress的异步执行机制并恰当运用cy.then()和Cypress.env(),您可以编写出更加健壮、可靠且易于维护的自动化测试脚本。
以上就是掌握Cypress异步命令与状态管理:解决测试中的执行顺序问题的详细内容,更多请关注php中文网其它相关文章!
每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号