The PageFactory
The PageFactory
原文地址:https://github.com/SeleniumHQ/selenium/wiki/PageFactory
In order to support the PageObject pattern, WebDriver's support library contains a factory class.//PageFactory是用来支持PageObject的。
好处一:自己决定是否缓存找到的元素。
好处二:只有用到页面上的一个元素时,才会去定位这个元素。
A Simple Example
In order to use the PageFactory, first declare some fields on a PageObject that are WebElements or List<WebElement>, for example://基于PageObject声明field和相关的方法。这里的field是一些元素变量。
package org.openqa.selenium.example;
import org.openqa.selenium.WebElement;
public class GoogleSearchPage {
// Here's the element
private WebElement q;
public void searchFor(String text) {
// And here we use it. Note that it looks like we've
// not properly instantiated it yet....
q.sendKeys(text);
q.submit();
}
}
In order for this code to work and not throw a NullPointerException because the "q" field isn't instantiated, we need to initialise the PageObject://初始化。
package org.openqa.selenium.example; import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.htmlunit.HtmlUnitDriver;
import org.openqa.selenium.support.PageFactory; public class UsingGoogleSearchPage {
public static void main(String[] args) {
// Create a new instance of a driver
WebDriver driver = new HtmlUnitDriver(); // Navigate to the right place
driver.get("http://www.google.com/"); // Create a new instance of the search page class
// and initialise any WebElement fields in it.
GoogleSearchPage page = PageFactory.initElements(driver, GoogleSearchPage.class); // And now do the search.
page.searchFor("Cheese");
}
}
Explanation
The PageFactory relies on using sensible defaults: the name of the field in the Java class is assumed to be the "id" or "name" of the element on the HTML page. That is, in the example above, the line://对上面样例程序的解释:声明field时,使用元素的id或者name。
q.sendKeys(text);
is equivalent to:
driver.findElement(By.id("q")).sendKeys(text);
The driver instance that's used is the one that's passed to the PageFactory's initElements method.
In the example given, we rely on the PageFactory to instantiate the instance of the PageObject. It does this by first looking for a constructor that takes "WebDriver" as its sole argument (public SomePage(WebDriver driver) {). If this is not present, then the default constructor is called. Sometimes, however, the PageObject depends on more than just an instance of the WebDriver interface. Should this be the case, it is possible to get the PageFactory to initialise the elements of an already constructed object://初始化时,可以使用xxxPage.class的一个实例。
ComplexPageObject page = new ComplexPageObject("expected title", driver);
// Note, we still need to pass in an instance of driver for the
// initialised elements to use
PageFactory.initElements(driver, page);
Making the Example Work Using Annotations
When we run the example, the PageFactory will search for an element on the page that matches the field name of the WebElement in the class. It does this by first looking for an element with a matching ID attribute. If this fails, the PageFactory falls back to searching for an element by the value of its "name" attribute.
Although the code works, someone who's not familiar with the source of the Google home page may not know that the name of the field is "q". Fortunately, we can pick a meaningful name and change the strategy used to look the element up using an annotation://使用注解,给元素变量取一个有意义的名字。
package org.openqa.selenium.example; import org.openqa.selenium.By;
import org.openqa.selenium.support.FindBy;
import org.openqa.selenium.support.How;
import org.openqa.selenium.WebElement; public class GoogleSearchPage {
// The element is now looked up using the name attribute
@FindBy(how = How.NAME, using = "q")
private WebElement searchBox; public void searchFor(String text) {
// We continue using the element just as before
searchBox.sendKeys(text);
searchBox.submit();
}
}
One wrinkle that remains is that every time we call a method on the WebElement, the driver will go and find it on the current page again. In an AJAX-heavy application this is what you would like to happen, but in the case of the Google search page we know that the element is always going to be there and won't change. We also know that we won't be navigating away from the page and returning (which would mean that a different element with the same name would be present) It would be handy if we could "cache" the element once we'd looked it up://使用PageFactory,有一个好处是,自己决定是否缓存找到的元素。默认情况下,每次调用方法时,都会重新去定位页面元素。这对于处理使用AJAX技术的页面很有用。处理其它的页面,可以找到元素后就缓存起来。
package org.openqa.selenium.example; import org.openqa.selenium.By;
import org.openqa.selenium.support.CacheLookup;
import org.openqa.selenium.support.FindBy;
import org.openqa.selenium.support.How;
import org.openqa.selenium.WebElement; public class GoogleSearchPage {
// The element is now looked up using the name attribute,
// and we never look it up once it has been used the first time
@FindBy(how = How.NAME, using = "q")
@CacheLookup
private WebElement searchBox; public void searchFor(String text) {
// We continue using the element just as before
searchBox.sendKeys(text);
searchBox.submit();
}
}
Reducing Verbosity
The example above is still a little verbose. A slightly cleaner way of annotating the field would be://简化注解
public class GoogleSearchPage {
@FindBy(name = "q")
private WebElement searchBox;
// The rest of the class is unchanged.
}
Notes
- If you use the PageFactory, you can assume that the fields are initialised. If you don't use the PageFactory, then NullPointerExceptions will be thrown if you make the assumption that the fields are already initialised.//使用PageFactory时,不要忘记初始化。
- List
<WebElement>fields are decorated if and only if they have @FindBy or @FindBys annotation. Default search strategy "by id or name" that works for WebElement fields is hardly suitable for lists because it is rare to have several elements with the same id or name on a page.//List<WebElement>使用@FindBy 或 @FindBys注解。 - WebElements are evaluated lazily. That is, if you never use a WebElement field in a PageObject, there will never be a call to "findElement" for it.//只有在用到页面上的一个元素时,才会去定位这个元素。
- The functionality works using dynamic proxies. This means that you shouldn't expect a WebElement to be a particular subclass, even if you know the type of the driver. For example, if you are using the HtmlUnitDriver, you shouldn't expect the WebElement field to be initialised with an instance of HtmlUnitWebElement.//要使用driver初始化,不要用webelement初始化。
The PageFactory的更多相关文章
- 浅析selenium的PageFactory模式
前面的文章介绍了selenium的PO模式,见文章:http://www.cnblogs.com/qiaoyeye/p/5220827.html.下面介绍一下PageFactory模式. 1.首先介绍 ...
- 在Python中实现PageFactory模式
关于 PageFactory 的概念主要是Java中内置了PageFactory类. import org.openqa.selenium.support.PageFactory; …… 例子,htt ...
- [小北De编程手记] : Lesson 08 - Selenium For C# 之 PageFactory & 团队构建
本文想跟大家分享的是Selenium对PageObject模式的支持和自动化测试团队的构建.<Selenium For C#>系列的文章写到这里已经接近尾声了,如果之前的文章你是一篇篇的读 ...
- Selenium的PageFactory在大型项目中的应用
出路出路,走出去了,总是会有路的:困难苦难,困在家里就是难. 因为最近遇到的技术问题一直没找到可行的解决办法,一直在翻看selenium的源代码,之前写测试代码的时候就是拿来即用,写什么功能啊,就按手 ...
- 使用页面对象模型(pageFactory)
页面对象模型可以使测试脚本有更高癿可维护性,减少了重复癿代码,把页面抽象出来. 页面对象设计模式提供了测试一个接口,测试可以像用户行为一样来操作页面. 通过隐藏页面元素定位,返有劣将测试代码和页面分离 ...
- 记我的第二次自动化尝试——selenium+pageobject+pagefactory实现自动化下单、退款、撤销回归测试
需求: 系统需要做下单.退款.撤销的回归测试,有下单页面,所以就想到用selenium做WEB UI 自动化 项目目录结构: common包上放通用的工具类方法和浏览器操作方法 pageobject包 ...
- UI分层中使用PageFactory
基于原PO设计模式,需要改变原有的从文件中读取文件,更改为PageFactory模式.做出如下改动: 1 2 public MsysPage(DriverBase driver) { super(dr ...
- PageObject&PageFactory
几篇介绍PageObject&PageFactory文章: PageFactory: http://code.google.com/p/selenium/wiki/PageFactory Pa ...
- Selenium的PageFactory & PageObject 在大型项目中的应用
因为最近遇到的技术问题一直没找到可行的解决办法,一直在翻看selenium的源代码,之前写测试代码的时候就是拿来即用,写什么功能啊,就按手动的操作步骤去转换,近日看到一个文章,又去wiki上查了查,觉 ...
- 浅析selenium的PageFactory模式 PageFactory初始化pageobject
1.首先介绍FindBy类: For example, these two annotations point to the same element: @FindBy(id = "foob ...
随机推荐
- Day 22 生成器yield表达式及内置函数(一丢丢)
本日知识点: ################################### #一.上节课复习:在for循环式,调用对象内部的__iter__方法, # 把他们变成了可迭代对象然后for循环调 ...
- Mybatis逆向生成使用扩展类
1.背景介绍 用的mybatis自动生成的插件,然而每次更改数据库的时候重新生成需要替换原有的mapper.xml文件,都要把之前业务相关的sql重新写一遍,感觉十分麻烦,就想着把自动生成的作为一个基 ...
- JAVA算法总结_时间复杂度_Demo
JAVA面试中经常问到排序算法问题,本人结合网络上一些资源整理了编写一下常用的Demo,并附带运行结果,希望能帮助到大家. /** * @Title: 冒泡排序 * @Description: 将数组 ...
- Windows系统Python包的安装
本文针对于Python初学者,Python老鸟请绕道. 最近同时尝试在Windows10.MacOS.Ubuntu三个系统上安装Python相关的包,整体比较,Ubuntu最简单,Windows10最 ...
- sql-server-next-version-ctp-1-4-now-available
https://blogs.technet.microsoft.com/dataplatforminsider/2017/03/17/sql-server-next-version-ctp-1-4-n ...
- 主流浏览器js 引擎内核市场份额attialx总结vOa9
原文: http://blog.csdn.net/attilax/article/details/40016... 时间: 2014-10-12 atitit.. 主流浏览器 js 引擎 内核 市场份 ...
- 老司机找bug的十年心路历程
一.码畜:靠编译器帮自己查语法错误 消灭笔误:编写适合程序猿的键盘练习 if (常量==变量或表达式) 使用goto接力超长的if,switch 连续的if还是if elseif 多个条件的组合:精心 ...
- android wifi相关模块 命令列表 汇总
static final int BASE =Protocol.BASE_WIFI; 131072 static final intCMD_START_SUPPLICANT = BASE +11; ...
- HDU 5304(Eastest Magical Day Seep Group's Summer-环加外向树生成树计数)[Template:Kirchhoff矩阵]
Eastest Magical Day Seep Group's Summer Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 655 ...
- Failure [INSTALL_FAILED_ALREADY_EXISTS]
1.发生原因 做unity开发的同事说apk无法安装,要我帮忙看下,然后我通过命令adb install安装apk,出现此提示 2.解决过程 首先想到的仍然是安装包已存在的问题,结果使用清理类软件清理 ...