当前位置: 首页 > 知识库问答 >
问题:

页面对象模型:为什么不在页面方法中包含断言?

闻人思聪
2023-03-14

第一次海报。我已经在UI自动化领域工作了很多年,但直到最近才被介绍/指示使用页面对象模型。其中大部分是常识,包括我已经使用过的技术,但是有一个特别好的点我还没有能够在我自己的头脑中证明,尽管我广泛地寻找一个合理的解释。我希望这里有人能启发我,因为当我试图将POM与我自己的最佳实践相结合时,这个问题已经引起了一些恐慌。

从http://code.google.com/p/selenium/wiki/PageObjects:

上面给出的代码显示了一个重要的观点:应该由测试而不是PageObjects负责对页面的状态进行断言。。。。当然,正如每一条指南一样,也有例外。。。

从…起http://seleniumhq.org/docs/06_test_design_considerations.html#chapter06-参考:

页面对象的设计方式有很大的灵活性,但是有一些基本规则可以用来获得测试代码所需的可维护性。页面对象本身永远不应该进行验证或断言。这是测试的一部分,应该始终在测试代码中,而不是在页面对象中。页面对象将包含页面的表示,页面通过方法提供的服务(但与测试内容相关的代码不应在页面对象中)。

有一个单一的验证可以而且应该在页面对象中,即验证页面以及页面上可能的关键元素是否正确加载。此验证应在实例化页面对象时进行。

这两个“指导原则”都允许潜在的例外,但我完全不同意基本前提。我习惯于在“页面方法”中进行大量验证,我认为验证的存在是一种强大的技术,可以在各种上下文中查找问题(即每次调用该方法时都会进行验证),而不仅仅是在特定测试的有限上下文中。

例如,让我们想象一下,当您登录到AUT时,会出现一些文本,上面写着“以用户身份登录”。让一个测试专门验证这一点是合适的,但是为什么不在每次调用登录时都验证它呢?这个工件与页面是否“正确加载”没有直接关系,也与“正在测试的内容”没有直接关系,因此根据上面的POM指南,它显然不应该在页面方法中。。。但在我看来,它显然应该存在,通过尽可能多地验证重要的工件,尽可能少地预先考虑,从而最大限度地提高自动化的能力。将验证代码放在页面方法中,通过允许您“免费”获得大量验证,而无需在测试中担心,从而增强了自动化的能力,并且在不同上下文中频繁进行验证通常会发现一些问题,如果验证仅限于以下情况,您将无法发现这些问题:,对该工件的单一测试。

换句话说,我倾向于区分特定于测试的验证和“一般”验证,我认为后者被广泛地包含在页面方法中是完全合适/可取的。这促进了更薄的测试和更厚的页面对象,这通常通过重用更多的代码来增加测试的可运维性——尽管这些准则中有相反的争论。我没说到重点吗?不希望在页面方法中进行验证的真正理由是什么?我所描述的情况实际上是这些指南中描述的“例外”之一吗,因此实际上与POM不一致?提前感谢你的想法。-jn-

共有3个答案

景俊拔
2023-03-14

您的页面对象不应该执行断言,因为页面对象必须知道您的测试框架(除非您使用内置语言断言)。但是您的页面需要知道它的状态以定位元素并执行操作。

关键在于“当然,每一条准则都有例外……”

您的页面应该抛出异常,而不是执行断言。这样,您的测试可以捕获断言并相应地放弃或采取行动。例如。

page = ProfilePage.open
try 
  page.ChangePassword(old, new)
catch notLoggedIn
  page.Login(user, pass)

assert page.contains "your password has been updated"

在这个有限的例子中,你必须反复检查,所以这可能不是最好的方法,但是你得到了这个想法。您也可以只检查状态(两次)

if page.hasLoginDialog
  page.Login

if page.hasLoginDialog //(again!)
  assert.fail("can't login")

你也可以检查一下你是否有个人资料页面

try 
  page = site.OpenProfilePage
catch notOnProfilePage

或者有你需要的元素尝试profilepage.change密码(旧的,新的)捕捉元素Not找到

或者不抛出异常

page = site.OpenProfilePage
if ! page instanceof ProfilePage

或者进行复杂的检查

assert page.looksLikeAProfilePage

重要的不是你怎么做。您希望将测试中的逻辑保持在最低限度,但不希望页面对象绑定到测试框架——毕竟,您可以使用相同的对象进行刮取或数据生成——或者使用具有自己断言的不同测试框架。

如果您觉得有必要,您可以将您的断言从测试用例中推到测试助手方法中。

page = site.GoToProfilePage
validate.looksLikeProfilePage(page)

如果你的语言支持它们,这是一个很好的混合机会,这样你就可以拥有干净的页面对象——并混合你的理智检查。

孟增
2023-03-14

我有时也会对这一建议感到困惑。我相信这条指导原则背后的原因是保持页面对象的可重用性,将断言放在页面对象中可能会限制它们被大量无关测试重用的能力。这就是说,我已经在我的页面对象上使用了某些验证方法,比如测试标题的标题——根据我的经验,这是封装页面中不改变的元素的测试逻辑的更好方法。

另一个注意事项是,我见过MVC应用程序将域模型重用为页面对象。如果操作正确,这可以显著减少测试库中的冗余代码。使用此模式,视图模型没有对测试框架的引用,因此很明显,您不能在其中放置任何断言。

龚镜
2023-03-14

作为指导方针,断言应该在测试中完成,而不是在页面对象中。当然,有时这不是一个务实的方法,但这些时间很少足以让上述指导方针正确。以下是我不喜欢在页面对象中使用断言的原因:

>

  • 阅读一个只调用验证方法的测试是非常令人沮丧的,因为断言隐藏在页面对象的其他地方。在可能的情况下,测试断言的内容应该是显而易见的;当断言直接出现在测试中时,这一点最好实现。通过在测试之外的某个地方隐藏断言,测试的意图就不那么清楚了。

    浏览器测试中的断言可能很昂贵——它们确实会减慢测试的速度。当您有数百或数千个测试时,可以将分钟/小时添加到您的测试执行时间中;这是一件坏事。如果您将断言转移到只关心那些特定断言的测试,您会发现您将有更快的测试,并且仍然会发现相关的缺陷。问题包括:

    将验证代码放在页面方法中可以让您“免费”获得大量验证,从而提高自动化的能力

    好的,“自由不是自由的”:)您实际乘以的是您的测试执行时间。

    到处都有断言违反了另一个好的指导方针;“每次测试一个断言”(http://blog.jayfields.com/2007/06/testing-one-assertion-per-test.html)。我不虔诚地坚持它,但我努力遵循原则。在可能的情况下,测试应该只对一件事感兴趣。

    测试的价值会降低,因为一个bug会导致测试负载失败,从而阻止他们测试应该测试的内容。

    例如,让我们想象一下,当您登录到AUT时,会出现一些文本,上面写着“以用户身份登录”。让一个测试专门验证这一点是合适的,但是为什么不在每次调用登录时都验证它呢?

    如果您在页面对象类中有断言,并且预期的文本发生了变化,那么登录的所有测试都将失败。相反,如果断言在测试中,那么只有一个测试会失败——那个专门测试正确消息的测试——让所有其他测试继续运行以找到其他错误。你不需要5000次测试来告诉你登录消息是错误的;1次测试就可以了;)

    让一个类做多件事违反了SOLID中的“S”,即“单一责任原则”(SRP)。一个类应该负责一件事,而且只负责一件事。在本例中,页面对象类应该负责对页面(或其部分)进行建模,仅此而已。如果它做的比这更多(例如:包括断言),那么您就违反了SRP。

  •  类似资料:
    • 我正在使用Selenium为我的网站构建一个测试框架,我实际上希望您在使用页面对象模型时对良好实践的想法:让我们说,我有一个欢迎页面,其中包含一个注销按钮存在的标题,这个标题可以在大多数页面中看到在我的页面中,我认为最好为标题写一个单独的类,比如: 公共类欢迎页 我的问题是,你认为在欢迎页面中包含标题作为属性更好还是应该将它们分开? 让我们以注销测试方法的代码为例: 案例一: 案例2: 第二个问题

    • 是否有任何Gem(比如siteprism:用于Web自动化测试)可以在我的移动自动化测试项目中使用,以使用页面对象模型模式定义屏幕。 提前谢谢

    • 我正在使用Perl和Selenium构建一个测试自动化项目。我正在使用页面对象模型。我有点不确定Selenium驱动程序将适合页面对象模型的实现。 每个页面对象是否应该“有”一个驱动程序?我的想法是,每个页面对象代表页面向用户提供的一组服务。考虑到这个概念,页面对象与驱动程序没有“has-a”关系。页面对象与驱动程序交互。不过,我仍在寻求建议。我应该将驱动程序作为web应用程序中每个页面对象的一部

    • 想象有一个页面在说http://google.com/AddUser在这里输入记录的详细信息,然后单击保存。完成此操作后,页面将重定向到 http://google.com/userList 您可以在其中查看用户列表,包括您刚刚输入的新记录。 如果我们按照页面对象模型,那么在和验证记录是否实际保存和显示的方法应该在 如果我们认为addUser和userList是两个类的对应对象,它会像下面这样:

    • 我下面的页面对象模型中,我已经放置了所有的WebElement地址和方法,即id,xpath等在页面中。示例:在登录页面上,我们有用户名字段、密码字段和登录按钮。因此,所有这些都将在LoginPage.java.本页还包括使用Webelements的方法。所以从实际的测试用例中,我只是调用页面上定义的方法。这就是我的困境。我有几个测试步骤需要我点击一个元素。所以说我需要点击链接1,链接2和链接3。

    • 问题内容: Selenium WebDriver中的页面对象模式是什么? 它的用途是什么?我们如何在Selenium WebDriver中使用它? 示例将不胜感激。 问题答案: 文档已经涵盖了这一点。如果您有任何具体问题,请随时编辑您的主要帖子。 官方: Selenuim Wiki上的页面对象和PageFactory。 Selenium官方网站上的页面对象设计模式。 非官方的: 进行Google搜