cypress - 赛普拉斯:想将方法定义为 POM
问题描述
我最近才开始参与 Cypress,并有使用 Selenium 的经验。我从 Selenium 了解到,您将元素和方法外包给通过页面对象模型分离的类,然后在测试中访问它们。因此,如果发生变化,您只需更改元素和方法一次,而不是在每次测试中都更改。
赛普拉斯也可以吗?
示例:我想将src
图像的 存储在方法中并将其作为返回返回。这是代码:
get_main_image_slider_active_picture_src() {
cy.get('.heroBanner.swiper-slide.swiper-slide-active img')
.should('have.attr','src')
.then((imgSrc) => {
const src = imgSrc;
})
return src;
}
不幸的是,我觉得这不像在 Selenium 中那样工作。
我该如何处理?
解决方案
关于这个主题有一些 SO 问题,值得一读。
本质上问题是 PO 方法通过同步返回值来工作,但赛普拉斯命令是异步的,你不能await
,你只能“链接”它们。
这个序列是一个链,
cy.get('.heroBanner.swiper-slide.swiper-slide-active img')
.should('have.attr','src')
.then(...
每个命令都会产生一个“主题”,它会沿链传递,
cy.get('.heroBanner.swiper-slide.swiper-slide-active img')
// subject === one or more <img> elements meeting the selector criteria
.should('have.attr','src')
// subject === the src attribute of the <img>
查找主题可以同步完成,但cy.get()
如果元素是从 api 获取或正在制作动画,也会重试。
简单的伪代码是
while (not found and not timeout) {
found = query the DOM for the selector
}
while 循环运行时间不确定,因此它是异步的。如果元素在超时之前没有出现,每个步骤也可能会失败。
所以使用 Cypress 命令的 PO 方法只能返回一个 Chainer,并且只能像异步 Cypress 命令(或自定义命令)一样使用。
页面对象
class HeroPage {
get_main_image_slider_active_picture_src() {
// here returning the final subject of this chain, wrapped as a chainer
return cy.get('.heroBanner.swiper-slide.swiper-slide-active img')
.should('have.attr','src')
}
}
测试
it('tests the picture page for kittens', () => {
const heroPage = new HeroPage()
heroPage.get_main_image_slider_active_picture_src()
.should(src => src.includes('kittens')) // chained subject
})
我对此的看法是
get_main_image_slider_active_picture_src
太具体了。在下一个测试中,您想要对<img>
自身进行断言,所以现在您创建另一个方法,或者重构所有内容以便返回 img 元素并在测试中执行所有断言。但是接下来你要测试 img 容器,那么合适的抽象级别是多少呢?Cypress 命令本身就很有表现力,那么它们真的需要 PO 抽象吗?
网页测试不像基于组件的框架,您可以在许多页面中重用一个组件。通常,一个,也许两个,规范涵盖一个网页,因此 PO 方法在许多页面上不是很可重用,例如,您的图像英雄 swiper 只会出现在一个页面上。例外情况可能是诸如登录之类的家务事。您可能会尝试参数化方法并使它们更通用 - 但这种努力似乎与获得的可重用性不成比例。
如果您在选择器中使用的元素类预计会发生变化,请使用 PO 仅返回选择器字符串(同步返回),例如
it('tests the picture page for kittens', () => { const heroPage = new HeroPage() cy.get(heroPage.activeImage) .should('have.attr','src') .should(src => src.includes('kittens')) })
您可以使用字符串模板构建选择器,
this.heroBanner = '.heroBanner'
this.swiper = `${this.herobanner}.swiper-slide`
this.activeSlide = `${this.swiper}.swiper-slide-active`
this.activeImage = `${this.activeSlide} img`
推荐阅读
- c# - 使用 Azure Http 触发器函数应用将 Cosmos DB 与 OData 集成
- python - 仅当它们包含粗体元素时如何提取html段落元素
- excel - if then elseif then 错误语句 excel vba
- android - Trouble Using Edit Search Function in Recycler View with Cards
- android - Tensorflow Lite 2.0+ 中 bindGlBufferToTensor 的任何替代方法?
- laravel - Laravel Forge - 通过裸 IP 而不是域名访问应用程序
- javascript - allDay 时段中的多天活动不会延续到其他日子
- oracle - Siebel crm,如何在另一台机器上打开 url?
- javascript - 如何在一个 html 页面中为每个 div 提供单独的 javascript 文件
- postgresql - 在 postgres 中选择日期时间