关于e2e测试:Cypress测试:.contains()等同于should(‘contain’)吗?

Cypress test: is .contains() equivalent to should('contain')?

是这个:cy.get('[name=planSelect]').contains(dummyPlan)

等效于此:cy.get('[name=planSelect]').should('contain', dummyPlan)

如果是这样,哪个是首选? 首先是更多的隐式断言,但在我看来更短,更清晰。

后续问题:环顾四周以了解如何最好地选择用于e2e测试的元素后,我发现Cypress文档建议使用data-cy属性。 是否有理由比仅将name属性添加到标记更好? name应该仅用于表单字段吗?


如果带有name=planSelect的元素不包含dummyPlan,则cypress测试的结果将是相同的,也就是说,此时测试将失败。

它们之间的区别在于,在第一种形式中,使用contains(),您实际上是在尝试选择一个元素,而cy.get(...)。contains()的结果将产生此预期的DOM元素,从而允许用于方法的进一步链接,例如:

1
cy.get('[name=planSelect]').contains(dummyPlan).click();

在第二种形式中,您将使用Chai链接器contain进行显式声明,以验证dummyPlan是否存在于其他元素中。

这是一个细微的差异,结果是相同的,但是我建议您仅在要在contains之后链接其他方法的情况下才使用cy.get('[name=planSelect]').contains(dummyPlan),如果要明确断言该元素,请使用第二种形式存在。从逻辑上讲,第一个代表通用测试失败(赛普拉斯试图找到一个不存在的元素),第二个代表显式声明失败(元素应包含dummyPlan,但不包含)。

关于第二个问题,name是有效的HTML属性,如果在原始功能中使用该属性(以命名输入字段)或该属性仅用于测试目的,则将其用于测试可能会引起混淆。 。我建议您按照文档中的建议使用cy-name,因为这样可以避免这种歧义,并明确指出此属性cy-name仅用于测试目的。

此外,在某些情况下,您可能决定从代码中剥离所有cy-name,然后再将其发送到生产环境(在构建过程中,使用某些webpack插件,例如string-replace-loader)。如果仅使用name,则将无法执行相同的操作,因为如果代码中有一些输入,则还将删除所需的输入name


回答

  • .contains(selector, content)是最佳选择器;重试
    元素选择并允许文本匹配(不只是
    .class #id [attributes])

  • .should()只是一个断言,仅重试该断言
    (不是元素选择)

除非您指定自己的名称,否则暗示.should('exist') -这是他们允许的方式.should('not.exist')

切线

浏览器支持XPath 1.0,这是一种基于DOM树遍历进行复杂查询的非常酷但模糊的方法。有一个包含谓词功能:

1
2
//*[         contains(normalize-space(.), 'The quick brown fox jumped over the lazy dog.') ]
   [not(.//*[contains(normalize-space(.), 'The quick brown fox jumped over the lazy dog.') ])]

这将从文档的根目录中搜索任何包含文本且不包含包含文本的后代节点的节点。
您可以在控制台中对其进行测试:

1
$x("//*[contains(normalize-space(.), 'The quick brown fox jumped over the lazy dog.')][not(.//*[contains(normalize-space(.), 'The quick brown fox jumped over the lazy dog.') ])]")