如何在稍后的测试中重用产生的值
How to reuse yielded value later in the test
上下文:我在第 1 页有一个带有 innerText 的元素,在第 2 页有另一个带有 innerText 的元素。我需要在第 3 页比较这两个值。所以我需要找到一种方法将这些值保存在变量中全局以便以后使用。
我尝试过的事情:
试验 1: 无效,因为 page1value 范围限于 cy.get()
cy.get('#selector').invoke('text').then(text => {
const page1value = text
})
试验 2: 不起作用,因为每当我尝试在外部打印值时,它都是未定义的或初始化时使用的值。
it('TC Name', () => {
let page1value,
cy.get('#selector').invoke('text').then(text => {
page1value = text
})
cy.log(page1value) //comes as undefined
})
试验 3: 使用 .as() 及其未定义的形式出现。
let page1value;
cy.get('#selector').invoke('text').as('page1value');
cy.log(page1value) //comes as undefined
如果有人能告诉我哪里做错了就好了。
Cypress 命令被推入(排队)到一个队列(称为命令队列 --- 它基本上是一个数组),然后串行(一个接一个)和异步执行。
虽然你的 cy.log()
也会异步执行,在上一个命令之后,你传递给它的值 (page1value
) 是 passed/evaluated 同步的,在你推送的时候队列的命令(在调用传递给 it()
的回调时评估---在测试开始时)。
这只是正常的 JavaScript 行为,与 Cypress 无关。所有命令 cy.*
都只是 cy
对象上的方法(函数),它们会立即被调用。没有立即调用(执行)的是每个命令执行的逻辑(例如,查询 DOM 以获取您提供给 cy.get()
的选择器,调用 cy.log('string')
时记录到命令日志,等)。
因此,在您的第二个示例中:
- 您声明
page1value
.
- 然后您立即将命令
cy.get()
、cy.invoke
、cy.then()
、 加入队列
- 你也立即入队
cy.log
,你将 page1value
传递给它(此时仍然是 undefined
)。
- 所有命令入队后,开始执行,从上到下。当
cy.then
命令轮流执行时,page1value
变量被赋值,但在测试的其余部分不再在任何地方使用(读取)它(回想一下,您在通过时已经读取过它它到上一步中的 cy.log
命令。
因此,您要做的是:
cy.get('#selector').invoke('text').then(text => {
cy.log(text);
});
在您的第 3 个示例中,如果您对某些内容进行了别名,则需要使用另一个命令访问该值(请记住,所有内容都是异步的,因此您无法访问异步设置的值,因为您以同步方式重新做),在这种情况下 cy.get('@aliasName')
:
cy.get('#selector').invoke('text').as('page1value');
cy.get('@page1value').then( value => {
cy.log(value);
});
请注意,为简单起见,以上解释略有不准确且不详尽(幕后发生的事情更多)。但作为事情如何运作的介绍,他们应该这样做。
无论如何,你一定要读一读Introduction to Cypress。
你也可以看看我之前涉及相关概念的回答:
- How to use a variable as a parameter in an API call in Cypress
上下文:我在第 1 页有一个带有 innerText 的元素,在第 2 页有另一个带有 innerText 的元素。我需要在第 3 页比较这两个值。所以我需要找到一种方法将这些值保存在变量中全局以便以后使用。
我尝试过的事情:
试验 1: 无效,因为 page1value 范围限于 cy.get()
cy.get('#selector').invoke('text').then(text => {
const page1value = text
})
试验 2: 不起作用,因为每当我尝试在外部打印值时,它都是未定义的或初始化时使用的值。
it('TC Name', () => {
let page1value,
cy.get('#selector').invoke('text').then(text => {
page1value = text
})
cy.log(page1value) //comes as undefined
})
试验 3: 使用 .as() 及其未定义的形式出现。
let page1value;
cy.get('#selector').invoke('text').as('page1value');
cy.log(page1value) //comes as undefined
如果有人能告诉我哪里做错了就好了。
Cypress 命令被推入(排队)到一个队列(称为命令队列 --- 它基本上是一个数组),然后串行(一个接一个)和异步执行。
虽然你的 cy.log()
也会异步执行,在上一个命令之后,你传递给它的值 (page1value
) 是 passed/evaluated 同步的,在你推送的时候队列的命令(在调用传递给 it()
的回调时评估---在测试开始时)。
这只是正常的 JavaScript 行为,与 Cypress 无关。所有命令 cy.*
都只是 cy
对象上的方法(函数),它们会立即被调用。没有立即调用(执行)的是每个命令执行的逻辑(例如,查询 DOM 以获取您提供给 cy.get()
的选择器,调用 cy.log('string')
时记录到命令日志,等)。
因此,在您的第二个示例中:
- 您声明
page1value
. - 然后您立即将命令
cy.get()
、cy.invoke
、cy.then()
、 加入队列
- 你也立即入队
cy.log
,你将page1value
传递给它(此时仍然是undefined
)。 - 所有命令入队后,开始执行,从上到下。当
cy.then
命令轮流执行时,page1value
变量被赋值,但在测试的其余部分不再在任何地方使用(读取)它(回想一下,您在通过时已经读取过它它到上一步中的cy.log
命令。
因此,您要做的是:
cy.get('#selector').invoke('text').then(text => {
cy.log(text);
});
在您的第 3 个示例中,如果您对某些内容进行了别名,则需要使用另一个命令访问该值(请记住,所有内容都是异步的,因此您无法访问异步设置的值,因为您以同步方式重新做),在这种情况下 cy.get('@aliasName')
:
cy.get('#selector').invoke('text').as('page1value');
cy.get('@page1value').then( value => {
cy.log(value);
});
请注意,为简单起见,以上解释略有不准确且不详尽(幕后发生的事情更多)。但作为事情如何运作的介绍,他们应该这样做。
无论如何,你一定要读一读Introduction to Cypress。
你也可以看看我之前涉及相关概念的回答:
- How to use a variable as a parameter in an API call in Cypress