2014-10-27 61 views
2

我到页面对象模式下面的链接和概念是好的,页对象模式DESGIN

https://code.google.com/p/selenium/wiki/PageObjects

这里是我的疑问:

public LoginPage typeUsername(String username) { 
    driver.findElement(usernameLocator).sendKeys(username); 
    return this;  
} 

public LoginPage typePassword(String password) { 
    driver.findElement(passwordLocator).sendKeys(password); 
    return this;  
} 


public HomePage submitLogin() {  
    driver.findElement(loginButtonLocator).submit(); 
    return new HomePage(driver);  
} 

以上硒呼叫包裹着一些功能我们在测试用例或任何页面级函数中调用这些函数,如下所示:

public HomePage loginAs(String username, String password) { 

     typeUsername(username); 
     typePassword(password); 
     return submitLogin(); 
    } 

我的疑问是:为什么我们不能直接调用sendkey或在整个项目中每次提交或点击。只有一行代码再次用我们自己的函数包装,这将需要更多的时间来运行代码。

是否有任何性能问题?

回答

1

恕我直言,关键好处是页面对象和测试独立进化。如果结构发生变化,则不要更改测试,反之亦然,如果要更改测试内容,则无需更改页面对象。将尝试在一个示例中说明这一点

想想写入的测试没有遵循页面对象模式,例如,测试产品细节。

this.driver(Find.By.id("username")).sendKeys(username); 
this.driver(Find.By.id("pass")).sendKeys(password); 
this.driver(Find.By.id("submit")).click(); 
// navigate to product listing page 
this.driver(Find.By.id("product-usb")).click(); 
// navigate to product details page 
this.driver(Find.By.id("product-a")).click(); 
assert(this and that); 

在这个例子中,如果结构发生变化(主要的重新设计),你可以强制改变你的测试。 现在,您正在预测变化,首先,您要确保没有代码重复,以便只在时间正确时在一个地方进行更改。拆分的方法的代码,最合理的分割是基于逻辑单元,而断言停留在测试他们属于

login(username, password); 
    moveToProductListing(); 
    selectProduct(productID); 
    assert(this and that); 

的问题是,当这些方法应该可以实现,这样就可以在测试中轻松访问它们。如果它的一个实用程序类,它将很快变得臃肿。进一步思考会导致您按页面对象进行分组。

您最终在测试中不知道正在测试的页面的结构(它隐藏在页面对象中)以及页面对象不知道您正在测试的特定断言的任何内容。

1

由于您已经开始使用Selenium文档。如果你看看这些Test design considerations,我想它也会有帮助。至于除了@Master从答案,你会看到

结束语硒呼吁

与任何编程,你将要使用 效用函数来处理,否则将被复制整个代码 你的测试。防止这种情况的一种方法是将经常使用的硒调用与您自己的 设计的函数或类方法进行包装。

并通过WebElements Presence的'安全操作'进行扩展。

关于Page对象,很高兴看到PageFactory的提示。

0

我认为这个问题和你的疑惑围绕上基本和furthor更多的我会尽量准确地回答

什么是页面对象设计模式?

好,页面对象是某种API来一个网页(或视图),您在您的系统拥有的,让我们把它看成是更多的“服务”页面给出了测试仪...

一旦它被看作是这样,我相信它更容易想到的动机......

页面对象知道它的内部匹配的HTML页面(或视图)和独自知道它...

例如,如果我们想要执行登录(作为用户),我们提供这些服务:

  • 我们在用户名输入中输入用户名。
  • 我们可以在密码输入中输入密码。
  • 我们可以点击'登录'按钮(预计失败或成功)。

当然还有更多的“服务”给出,但我们可以在这里停下来回到关键点......我们应该如何处理这些“服务”?这很容易:

我们需要创建一个“LoginPage”对象,它知道页面的(私人)选择器和HTML构造(ids,classes,xpaths等等)。测试人员公开什么?我们刚刚讨论过的服务...

测试人员可以要求登录页面输入“TypeUsername(string inputUsername)”或TypePassword(string inputPassword) - 如果您是“LoginAsDefaultUser()”,也可以添加“Services”使用此页面来测试其他的网页...

的问题

尽管这一个良好的开端,它留下了很多改进的余地。

最明显的问题是,我们可能需要跨多个页面对象进行常见操作。而用我们目前的方法,我们最终会得到重复的代码。

解法

当创建的BasePage对象,它包装硒核心,并且每个页继承从当前页(直接或直接)我们正在创建没有耦合,如果某处的页面的动态环境(或视图)已经改变,你只需要修复一个特定的对象。

摘要

  • 即使它被称为页面对象设计模式,它更是一个视图对象的设计模式,例如:如果在你的平台上存在对每一个返回左边的菜单页面,您可以创建“MyPlatformBasePage”,并且每个视图都将从它继承(并且代码复制再次消失,胜利!)
  • 页面对象只公开提供的“服务”,请勿公开Selenium内部。
  • 页面对象不是测试,不要断言其结果。
  • 方法返回其他PageObjects,例如:调用“LoginAsDefaultUser”的LoginPage将导航到我们的应用程序主页,因此我们必须返回我们的“HomePage”对象。
  • 使用干净的代码原则,您提供的不同“服务”将用不同的方法表示,不要通过布尔变量来改变“服务”的逻辑。

动机

  • 每个人都可以写信这些测试,甚至非技术的问题答案
  • 代码现在是completey动态和封装
  • 使用外观层(或基页),您可以潜力取代硒或改变版本没有一个巨大的麻烦。