背景:多年来,在Selenium UI自动化中,我们所有人都一直使用Page Objects模式作为“最佳实践”。在页面对象中,“方法”与页面紧密耦合,而不是通用的上下文无关功能。根据我的观察,70-80%的页面对象方法代码不能在其他Web应用程序中直接重用,因为每个页面对象方法都高度专用于给定Web应用程序中的特定页面。

我们还可以通过简单地定义一个对象集合(对象存储库)和一组对其进行操作的定义良好的动作/实用函数,可以获得相同的抽象水平(如果不是更好的话)。

那么确切的是使用页面对象模式的观点,我们可以使用简单的函数,这些函数可以在不同的上下文中重复使用。因此,难道我们不是要在页面对象中进行耦合吗?

难题:从根本上讲,在任何UI自动化中我们都可以执行一些UI操作。当我们在页面的上下文中定义方法时,我们不是在通用的“无上下文函数”上创建专用的“方法”吗?

示例:页面对象方法(例如“ click Submit_user_button”)特定于页面,即使在其他页面的同一应用程序中也可能无法直接重用!

我强烈认为,这是否在损害我们的灵活性=>可重用性=>可维护性?

评论

sqa.stackexchange.com/a/17904/8992

我之所以拒绝,原因很简单。我发现很难解析和理解长句子。您能否通过缩短句子,在下一个语句开始时加点来重新表达您的问题?

我试图用较短的句子重新表述。

谢谢。自由流动的抽象功能意味着什么?能举个例子吗?同样,对象存储库似乎起源于QTP,但对我而言它具有模糊的含义。您能解释一下对象存储库中存储的内容并举个例子吗?我想既有特定于某些页面的方法,又有对不同页面有用的方法。仅通过查看示例,我就能给出更具体的答案。

顾名思义,它可以自由流动,而不受页面之类的限制。类似地,对象存储库可以是要存储的任何数据结构或格式,包括Json,xml等。

#1 楼

那不是pageObject的本质所在:页面上UI元素的描述以及如何与之交互。

现在编写测试时,您经常以某种方式与多个元素交互实现工作流程。现在,如果多个测试使用相同的工作流程,则将工作流程步骤的组合也移至pageObject中可能是有意义的,以便其他测试可以重新使用它。我不会从此开始,只需将其保持干燥即可。

将所有UI元素及其交互拆分为页面和工作流只会使其更易于阅读,理解如何以及何时使用它们。 />
我真的不明白这是如何使事情复杂化的。创建抽象,解耦并将其存储在大约100行的文件中是程序员谋生的工作。

创建pageObject时,请不要一开始就过度设计它们。牢记YAGNI原则。

我喜欢做得好的页面对象的原因是,您将浏览器的驱动程序与测试分离了。测试与页面交互,页面与驱动程序交互。测试不知道驱动程序。这意味着您可以在理论上不更改测试的情况下将驱动程序从Selenium切换到Cypress。

评论


可能“过于复杂”是不正确的词。我的意思是``过度耦合''。

– Vishal Aggarwal
18年8月18日在14:52

在基于大型/复杂UI的应用程序中,我们通常会获得远大于100行的页面对象。

– Vishal Aggarwal
18年8月27日在11:41

啊,您的意思是那些试图将所有功能放在单个屏幕/页面中的应用程序,这是另一种令人反感的反模式。我想理想情况下,课程应该在100-500行左右。如果您的pageObjects较大,则可能有一些子类,或者可以将页面拆分为多个区域。另请参阅:softwareengineering.stackexchange.com/questions/66523/…

– Niels van Reijmersdal
18年8月27日12:00



#2 楼

页面对象在较小的站点中很好地工作,这些站点很少或根本没有重复使用字段,因为耦合效果不足以引起重大问题-在可读性测试,DRY,YAGNI和SOLID之间找到平衡点总是会遇到挑战。 。

我发现,一旦应用程序足够大,最好在输入类型对象方面进行工作,以便测试代码传递定位器信息以及任何要输入的数据。

这大大简化了我的测试代码:我有一个对象来处理编辑类型的输入,另一个对象用于可单击字段(按钮,链接等),另一个对象用于复选框,一个对象用于下拉列表,依此类推。向前。这使我的页面对象成为单个通用对象,可以调用FindAndClick(string id)FindAndEnterText(string id, string text)等方法。(然后我进行数据驱动测试,以便测试工具从CSV文件中读取ID,文本等)。 >

评论


您仍然应该使用页面对象的“经典”定义...随着站点和套件的变大,它变得越来越重要。您仍然可以使用特定的功能来处理特定的元素,但是这些元素将在页面对象中被引用/使用。页面对象提供了组织,而您的元素函数提供了一种DRY方式来处理页面上的那些元素。您可以(可能应该)同时拥有两者。

– JeffC
18年8月20日在13:10

@JeffC-我发现它不能很好地工作,因为与我一起工作的网站有太多地方,唯一的区别是元素所在的页面。不得不为每个页面(一个页面除外)定义一个注销元素,或者构建一个过于复杂的继承结构,以便可以从页面访问标头元素(每个页面对象都需要引用),这变得太麻烦了。

–凯特·保罗(Kate Paulk)
18年8月20日在13:33

在这种情况下,构建标题面板页面对象并根据需要使用它。页面对象不必代表整个页面,而可以代表任何重复的功能。您可以有一个日历小部件页面对象或一个登录对话框页面对象,依此类推。

– JeffC
18年8月20日在13:37

#3 楼

PageObjects一词已被过度使用(包括我在内)。要重置:

我们有元素定位器。
有时我们的元素定位器还具有一个操作(例如点击)。
某些元素定位器位于页面级别,但其他元素定位器可以视为片段,框架,工作流或特定于域的分组级别

这些定位器是然后基本上可以通过两种方式访问​​-直接在测试脚本的顶层,例如click user_submit_button或您的自定义DSL可能是submit_user_form,然后函数submit_user_form本身具有click user_submit_button行,并且user_submit_button在下一个较低的页面对象级别定义。

无论哪种情况,这两个关键角色该页面对象所服务的是:


减少由于相同元素的重复定义而导致的错误
将该对象命名以使其更具可读性和易于维护

您想让代码读起来更像

click submit_user_button

,而不是像

click(find('div.users span#inputform button'))

在这里创建的是非常特定和选择性的函数,而不是通用函数,但是在这种情况下,通用函数根本不是编写此类特定测试代码的唯一目标。我们正在使代码可维护,这就是目标。我见过不使用Page Objects的代码,看起来很快就很难看。

评论


据我了解,任何特定的代码灵活性都较差,因此可重用性较低,而任何可重用性较低的代码则难以维护。是不是

– Vishal Aggarwal
18年8月19日在5:05

可重用性是好的代码的一个属性,但是必须在其他方面和考虑到其他因素的特定情况之间进行权衡。编程就是平衡多个问题

–迈克尔·杜兰特(Michael Durrant)
18年8月19日在11:04

适当时,可重用性很好。但是,当两个对象是不同的东西时,给它们唯一的名称仍然很好。

–迈克尔·杜兰特(Michael Durrant)
18年8月19日在11:09

对于UI自动化,可维护性是在代码中实现的主要目标。从长远来看,不同页面中的诸如“ click Submit_user_button”和“ click_order_save_button”之类的功能是维护的噩梦。

– Vishal Aggarwal
18年8月20日在2:46

同样,这些所谓的页面类没有任何内部状态可以防止外部世界发生突变。我们永远不会在运行时更改定位器定义。

– Vishal Aggarwal
18年8月20日在3:04

#4 楼

在我看来,Page Objects不会在代码中引入抽象,因为在定义页面对象时,您会对页面的特定元素执行此操作。我也不会反对Page ObjectsObject Repository,因为基本上对象存储库旨在存储页面对象。

当我使用Page Object模式时,我可以看到将该架构模式与OOP概念和编程语言提供的工具结合起来的最大价值。例如,您可以定义绑定到类的页面对象,然后通过添加其他对象/隐藏现有对象来扩展该类。这将帮助您遵循应用程序的实现,因为这是在应用程序的不同位置重用UI组件并扩展组件功能(使用页面对象时可以通过继承解决的功能)的常见做法,例如取决于用户具有的角色。