【问题标题】:Why use Page Factory?为什么要使用页面工厂?
【发布时间】:2018-03-01 23:17:35
【问题描述】:

我是一名新的测试工程师,一直在阅读有关页面对象模型并实现它们的内容,并且不断遇到页面工厂。我知道 Page Factory 是一个 POM,它提供了额外的功能,例如在调用 Page Factory 时实例化所有元素以及用于测试的更具可读性的代码(尽管我并不完全了解可读性)。需要明确的是,我在 POM 上出售。代码的可重用性和相对易于维护性非常好,我正在朝着这个方向发展。

我归结为两个问题:

  • 为什么我要实例化所有元素而不是即时执行?
  • Page Factory 有哪些我缺少的优势?

【问题讨论】:

    标签: c# selenium testing automated-tests qa


    【解决方案1】:

    这是 Selenium 项目负责人兼 Page Factory 的创建者 Simon Stewart,在 2017 年奥斯汀 SeleniumConf 上。在他的主题演讲中,他说不要使用 Page Factory。演讲的这一部分从这里开始:

    https://youtu.be/gyfUpOysIF8?t=1517

    实际声明时间为 27:25。

    【讨论】:

    • 这是一场精彩的演讲,值得花时间观看。这是我不打算使用页面工厂的部分原因。这和网络应用的工作方式意味着很多过时的元素会导致问题。
    • 这不是问题的答案。应该是评论。
    • @DebanjanB 他问为什么要使用页面工厂,来自 Selenium 主要贡献者(和其他人)的答案是不要,他解释了原因。这怎么不是问题的答案?
    • @JeffC OP 的 2 个问题非常清楚,1)为什么我要实例化所有元素而不是即时执行? 2)我缺少的Page Factory的优势是什么?您的答案没有解决其中任何一个问题。相反,您指出了西蒙对特定用例的评论,他说不要。但这并不适用于所有人。 PageFactoryPOM 仍然是测试自动化的一种更好的方法。
    • @JeffC 虽然他反复说不要使用 PageFactory,但他并没有真正解释原因。 “API 很糟糕”或“人们不自己编写”并没有提供太多技术理由来说明原因。该部分可能比仅仅咆哮它提供更多信息。
    【解决方案2】:

    一些答案​​说 PageFactory 在实例化时会“加载”所有 WebElement - 这实际上是不正确的。

    元素在您访问它们之前不会加载。它是通过基类和 RealProxy 完成的。它确实使用了底层的标准 FindElement(s)By 方法,因此拥有 WebElement 与存储 By 并在需要时加载它们并没有真正的性能优势。

    我选择不使用 PageFactory 模型的一个原因是,我可能要搜索一个我想要存在的元素,并且通过使用自动连接的方法,它会搜索在我可以在测试中说“不存在”之前查看它是否存在。

    另一个问题是 PageFactory 如何实例化 WebElement 与 Driver.FindBy 如何实例化它们之间存在细微差别。困扰我的一个问题是 PageFactory 的版本没有实现IWrapsDriver,这意味着您无法获取用于从元素中查找元素的驱动程序。这可能看起来不多,但这意味着当您想为 WebElement 方法编写扩展而需要驱动程序时,您必须找到一种(更复杂的)获取驱动程序的方法,特别是因为我认为 PageObjectModel 应该没有直接引用驱动程序...

    但是,在很多情况下,开箱即用的 PageFactory 方法非常好。我认为使用或不使用 PageFactory 的关键在于对测试代码和页面对象模型如何工作和交互采用一致的方法——因为这是可维护性的关键。

    【讨论】:

    • 当我深入研究这个问题时,您的答案与我发现的关于实例化的内容相符。但是,对于我正在测试的 Web 应用程序的工作方式,我必须处理许多导致问题的陈旧元素。到目前为止,我认为页面工厂不是这个项目的好选择。我将使用 POM。
    • 那么,您的 PageObject 类对于元素的初始化看起来如何?特别是对于那些有时在场但并不总是依赖于数据的人。
    • @FDM,这对我来说已经过去了一段时间,我已经转向不依赖 selenium/c# 的不同项目。但是,我的页面模型有一系列我需要访问的元素的选择器,可能看起来像:private By SomeLink => By.CssSelector("a"); 然后是一系列可能与它们交互的方法,例如public AnotherPageModel ClickSomeLink() => NavigateTo<AnotherPageModel>(SomeLink)。 NavigateTo 只是执行“单击并等待”(单击并等待所有脚本执行),然后返回代表新状态的新页面模型。
    【解决方案3】:

    为什么我要实例化所有元素而不是即时执行?

    如果我没记错的话,PageFactory 会扫描任何WebElement 属性/字段及其属性,并用代理包装它们。那时你还没有接触 Selenium 服务器(你可以在服务器控制台输出中检查它)。一旦您尝试访问该属性,WebElement 就会被实例化。因此,如果您只访问一个 PO 属性/字段,则仅创建一个 WebElement

    我缺少的 Page Factory 的优点是什么?

    属性的使用使代码更具可读性并且易于生成。创建一个为您生成PageObjects 的工具是很常见的。

    PageFactory 是为了支持 PageObject 模式而创建的,仅此而已。您不必一定要使用它才能采用 PO 方式。

    最后,如果您对它的详细工作原理感到好奇,我建议您查看源代码。这是我刚开始使用 Selenium 时所做的。

    【讨论】:

      【解决方案4】:

      为什么我要实例化所有元素而不是即时进行?

      一般来说,当我们通过PageFactory 启动任何页面类时,它使我们能够同时加载所有期望的(定义的)WebElements,我们打算在粗略的测试执行中与之交互。

      我缺少的 Page Factory 的优点是什么?

      使用Page Factory 的好处很多。其中一些如下:

      1. 页面工厂使您的框架更加结构化、健壮和可维护。
      2. 任何单个/多个页面的DOM Tree 的更改都可以轻松适应。
      3. 通过Page Factory@Test类、BrowserFactoryPage Objects之间的不同调用em>断言变得更加干净和高效。
      4. Page Factory 的附加属性,如 FindBy()FindBysCacheLookup,极大地加速了我们的测试执行

      【讨论】:

      • 您的回答有很多方面是错误的。 PageFactory 不会在类加载时加载所有元素。它是根据需要/请求的。有关更多详细信息,请参阅我的答案中的 YT 链接或进行一些谷歌搜索。它并没有消除对适当等待的需要。它不会使框架更加结构化,我认为您将它与正确实现的页面对象模型混淆了。
      • @JeffC 谢谢。 1)我确实提到了enables us to load all the desired (defined) WebElements。 2)你能指出一些你为什么相信It doesn't make the framework more structured的文件。 3)IMO,PageFactory 仅通过POM 实现,如果我错了,请参考一些具体的文档。 4) 根据您的建议,删除了对waits 的引用。
      • 1) 你说,when we initiate any page class through PageFactory, it enables us to load all the desired (defined) WebElements at the same time 这让我觉得你相信所有的元素都是在实例化时被刮掉的(就像很多人一样,包括我在内)。请参阅其他一些答案以进行更正。 2) 它本身并没有使 POM 变得更好。 POM 的实现是好是坏,PageFactory 并不会真正影响它。 3)同意..不确定这是从哪里来的?
      • @JeffC 再次感谢。 1) made me think that you believe that all the elements are scraped on instantiation 一点也不。 2)我的理解是当你说make POM better时,主要因素之一是better structured。如果我错了,请指出我的文档。 3)如果你是not sure where this came from,一个小谷歌会把它拿出来。 由于答案现在已更新,并且在没有任何具体文件反对我的观点的情况下,您能否撤回您的反对票?
      • PageFactory 只是一个工厂类......它只是帮助初始化页面对象。您在描述它的优势时所归因的远不止这些。您可能应该花一些时间了解 PageFactory 实际上是什么。你没有提供任何官方文件来证明你的陈述。这是支持我的声明的官方文档的链接,该页面没有提到您声称它提供的任何优势,github.com/SeleniumHQ/selenium/wiki/PageFactory
      【解决方案5】:
      • 为什么我要实例化所有元素而不是即时进行?

        PageFactory 可用于初始化 Page 类的元素,而无需使用 FindElement 或 FindElements。当您更多地使用 webelement(s) 时,一旦您的代码变得更好的可读性。

      • 我缺少的 Page Factory 有哪些优势?

        您还可以在 Page Factory 中使用一些属性。最明显的是 FindsBy 属性,但您也可以使用 CacheLookup 属性在元素被查找一次后对其进行缓存。

      【讨论】:

      • Koen,第一部分是有道理的。您是说如果我多次需要它,它可以通过减少在页面上查找元素的调用次数来简化代码。在第二部分,我阅读了有关 CacheLookup 的问题。具体来说,如果 Web 元素不存在或无法找到,它将以一个不起作用的占位符结束,并产生难以追踪的错误。其次,如何避免使用 CacheLookup 过时元素的风险?我知道如果我称它为存在且存在,但如果我调用了存在于多个页面上的元素,它可能会过时。
      • 并非每个网站都适合使用 CacheLookup 注释/属性。我认为当在网站上使用大量 Ajax 调用和/或 Javascript 时,风险会变得更大。您将看到更多陈旧元素异常。但是当一个站点非常静态时,CacheLookup 将是一个好主意。
      • 我明白了。我希望我不会在 Tririga 上大量使用 CacheLookup,因为它都是 JavaScript。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-07-05
      • 2021-04-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-10-14
      相关资源
      最近更新 更多