Selenium Webdriver 的 PageObject 改造
PageObject中提供了一个@FindBy注解,也非常好用,但由于其是一次性全部初始化所有的WebElement,对于当前还不存在于页面上的Element在初始化时就会报错,为了解决这个问题,自然就不能用这个@FindBy注解了,而我们可以自已去写一个类似的注解来解决这个问题,下面是思路的实现:
自定义一个@FindBy注解
@Retention(RetentionPolicy.RUNTIME)
@Target({ ElementType.FIELD })
public @interface FindBy {
String name();
int age();
int lazy() default 0;
}
定义一个TestInfo类来模拟WebElement类
public class TestInfo {
private String name;
private int age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "TestInfo [name=" + name + ", age=" + age + "]";
}
}
解析@FindBy注解
public class PageUtil {
private static void initialLazyInfo(Object obj, int lazy) {
try{
Field[] fields = obj.getClass().getDeclaredFields();
for (Field field : fields) {
if(field.isAnnotationPresent(FindBy.class) && field.getType().equals(TestInfo.class)){
FindBy findBy = field.getAnnotation(FindBy.class);
if(findBy.lazy()==lazy){
TestInfo temp = new TestInfo();
temp.setName(findBy.name());
temp.setAge(findBy.age());
field.setAccessible(true);
field.set(obj, temp);
}
}
}
}catch(Exception e){
e.printStackTrace();
}
}
public static void initialLazy(Object obj){
PageUtil.initialLazyInfo(obj, 0);
}
public static void initialLazy(Object obj, int lazy){
PageUtil.initialLazyInfo(obj, lazy);
}
}
使用方式
public class DemoPage {
public DemoPage() {
PageUtil.initialLazy(this);
}
@FindBy(name="zf1", age=1)
private TestInfo info1;
@FindBy(name="zf2", age=2, lazy=1)
private TestInfo info2;
public void test(){
System.out.println("info1 is: " + info1);
System.out.println("info2 is: " + info2);
PageUtil.initialLazy(this, 1);
System.out.println("info2 is: " + info2);
}
public static void main(String[] args) {
DemoPage dp = new DemoPage();
dp.test();
}
}
运行结果
info1 is: TestInfo [name=zf1, age=1]
info2 is: null
info2 is: TestInfo [name=zf2, age=2]
说明
- 将TestInfo初始化进行了分层次的初始化
- 在需要用到的地方用
PageUtil.initialLazy(this, int);进行初始化
以上虽然实现了分层次的初始化,但是在要用到的地方都需要调用PageUtil.initialLazy(this, int);,还是显得有点麻烦,要解决这个问题,还得从改造WebElement类开始,然后自定义一个@FindBy注解,并且在需要用到元素的地方再去判断并初始化。
定义@FindBy注解
@Retention(RetentionPolicy.RUNTIME)
@Target({ ElementType.FIELD })
public @interface FindBy {
String id() default "";
String name() default "";
String className() default "";
String css() default "";
String tagName() default "";
String linkText() default "";
String partialLinkText() default "";
String xpath() default "";
}
将@FindBy注解中的值结赋到一个中间类中去,在Page类进行初始化的时候进行赋值
public class FindElement {
private String id;
private String name;
private String className;
private String css;
private String tagName;
private String linkText;
private String partialLinkText;
private String xpath;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getClassName() {
return className;
}
public void setClassName(String className) {
this.className = className;
}
public String getCss() {
return css;
}
public void setCss(String css) {
this.css = css;
}
public String getTagName() {
return tagName;
}
public void setTagName(String tagName) {
this.tagName = tagName;
}
public String getLinkText() {
return linkText;
}
public void setLinkText(String linkText) {
this.linkText = linkText;
}
public String getPartialLinkText() {
return partialLinkText;
}
public void setPartialLinkText(String partialLinkText) {
this.partialLinkText = partialLinkText;
}
public String getXpath() {
return xpath;
}
public void setXpath(String xpath) {
this.xpath = xpath;
}
}
Page类实例化时初始化@FindBy注解并赋值给FindElement类
public class PageUtil {
public static void initialWebElement(Object obj) {
try{
Field[] fields = obj.getClass().getDeclaredFields();
for (Field field : fields) {
if(field.isAnnotationPresent(FindBy.class) && field.getType().equals(WebElement.class)){
FindBy findBy = field.getAnnotation(FindBy.class);
FindElement findElement = new FindElement();
if(!"".equals(findBy.id())){
findElement.setId(findBy.id());
}else if(!"".equals(findBy.name())){
findElement.setName(findBy.name());
}else if(!"".equals(findBy.className())){
findElement.setClassName(findBy.className());
}else if(!"".equals(findBy.css())){
findElement.setCss(findBy.css());
}else if(!"".equals(findBy.tagName())){
findElement.setTagName(findBy.tagName());
}else if(!"".equals(findBy.linkText())){
findElement.setLinkText(findBy.linkText());
}else if(!"".equals(findBy.partialLinkText())){
findElement.setPartialLinkText(findBy.partialLinkText());
}else if(!"".equals(findBy.xpath())){
findElement.setXpath(findBy.xpath());
}
WebElementExt ext = new WebElementExt(findElement);
field.setAccessible(true);
field.set(obj, ext);
}
}
}catch(Exception e){
e.printStackTrace();
}
}
}
改造WebElement类,利用的是装饰器模式
public class WebElementExt implements WebElement {
private static WebDriver driver = new FirefoxDriver();
private FindElement findElement;
public WebElementExt(FindElement findElement) {
this.findElement = findElement;
}
private WebElement element;
private WebElement getWebElement(){
if(element != null){
return element;
}
if(findElement.getId() != null){
element = this.waitForElement(By.id(findElement.getId()));
}else if(findElement.getName() != null){
element = this.waitForElement(By.name(findElement.getName()));
}else if(findElement.getClassName() != null){
element = this.waitForElement(By.className(findElement.getClassName()));
}else if(findElement.getCss() != null){
element = this.waitForElement(By.cssSelector(findElement.getCss()));
}else if(findElement.getTagName() != null){
element = this.waitForElement(By.tagName(findElement.getTagName()));
}else if(findElement.getLinkText() != null){
element = this.waitForElement(By.linkText(findElement.getLinkText()));
}else if(findElement.getPartialLinkText() != null){
element = this.waitForElement(By.partialLinkText(findElement.getPartialLinkText()));
}else if(findElement.getXpath() != null){
element = this.waitForElement(By.xpath(findElement.getXpath()));
}
if(this.waitElementToBeDisplayed(element)){
return element;
}
return null;
}
private WebElement waitForElement(final By by) {
WebElement element = null;
try {
element = new WebDriverWait(driver, 20).until(new ExpectedCondition<WebElement>() {
public WebElement apply(WebDriver d) {
return d.findElement(by);
}
});
} catch (Exception e) {
e.printStackTrace();
}
return element;
}
private boolean waitElementToBeDisplayed(final WebElement element) {
boolean wait = false;
if (element == null)
return wait;
try {
wait = new WebDriverWait(driver, 20).until(new ExpectedCondition<Boolean>() {
public Boolean apply(WebDriver d) {
return element.isDisplayed();
}
});
} catch (Exception e) {
e.printStackTrace();
}
return wait;
}
@Override
public void click() {
this.getWebElement();
element.click();
}
@Override
public void submit() {
this.getWebElement();
element.submit();
}
@Override
public void sendKeys(CharSequence... charSequences) {
this.getWebElement();
element.sendKeys(charSequences);
}
@Override
public void clear() {
this.getWebElement();
element.clear();
}
@Override
public String getTagName() {
this.getWebElement();
return element.getTagName();
}
@Override
public String getAttribute(String s) {
this.getWebElement();
return element.getAttribute(s);
}
@Override
public boolean isSelected() {
this.getWebElement();
return element.isSelected();
}
@Override
public boolean isEnabled() {
this.getWebElement();
return element.isEnabled();
}
@Override
public String getText() {
this.getWebElement();
return element.getText();
}
@Override
public List<WebElement> findElements(By by) {
this.getWebElement();
return element.findElements(by);
}
@Override
public WebElement findElement(By by) {
this.getWebElement();
return element.findElement(by);
}
@Override
public boolean isDisplayed() {
this.getWebElement();
return element.isDisplayed();
}
@Override
public Point getLocation() {
this.getWebElement();
return element.getLocation();
}
@Override
public Dimension getSize() {
this.getWebElement();
return element.getSize();
}
@Override
public String getCssValue(String s) {
this.getWebElement();
return element.getCssValue(s);
}
}
使用方法
public class DemoPage {
public DemoPage() {
PageUtil.initialWebElement(this);
}
@FindBy(xpath="//abc")
private WebElement element;
public void clieckButton(){
element.click();
}
}
经过上面这样改造后,即便是页面中动态加载的元素,也不用担心会报错了,也不用多次初始化了!
https://testerhome.com/topics/10803
Selenium Webdriver 的 PageObject 改造的更多相关文章
- 【转】Webdriver的PageObject改造By 张飞
Webdriver的PageObject改造 PageObject中提供了一个@FindBy注解,也非常好用,但由于其是一次性全部初始化所有的WebElement,对于当前还不存在于页面上的Eleme ...
- Selenium WebDriver 数据驱动测试框架
Selenium WebDriver 数据驱动测试框架,以QQ邮箱添加联系人为示例,测试框架结构如下图,详细内容请阅读吴晓华编著<Selenium WebDiver 实战宝典>: Obje ...
- 使用httpclient 调用selenium webdriver
结合上次研究的selenium webdriver potocol ,自己写http request调用remote driver代替selenium API selenium web driver ...
- Selenium的PO模式(Page Object Model)|(Selenium Webdriver For Python)
研究Selenium + python 自动化测试有近两个月了,不能说非常熟练,起码对selenium自动化的执行有了深入的认识. 从最初无结构的代码,到类的使用,方法封装,从原始函数 ...
- Selenium WebDriver 之 PageObjects 模式 by Example
目录 1. 项目配置 2. 一个WebDriver简单例子 3. 使用Page Objects模式 4. 总结 5. Troubleshooting 6. 参考文档 本篇文章通过例子来阐述一下Sele ...
- Selenium WebDriver Code
Selenium WebDriver 用于模拟浏览器的功能,可以做网站测试用,也可以用来做crawler.我是用eclipse开发的,导入selenium-server-standalone-***. ...
- selenium webdriver 右键另存为下载文件(结合robot and autoIt)
首先感谢Lakshay Sharma 大神的指导 最近一直在研究selenium webdriver右键菜单,发现selenium webdriver 无法操作浏览器右键菜单,如图 如果我想右键另存为 ...
- Selenium Webdriver java 积累一
Selenium Webdriver 学习: http://jarvi.iteye.com/category/203994 https://github.com/easonhan007/webdriv ...
- Selenium Webdriver下click失效问题解决
最近在使用Selenium Webdriver(Selenium2.0)进行界面自动化测试的时候发现单击事件无效,通过driver.findElement的方式是可以找到click元素的,但是就是cl ...
随机推荐
- PHP程序员如何理解IoC/DI(转)
php - Dependency Injection依赖注入 和 自动加载 各自的优缺点 ioc/di和自动加载时两回事. ioc/di 让代码由创建对象改为注入对象,是一种编程思想,而自动加载,只是 ...
- python MQTT 出现TypeError: payload must be a string, bytearray, int, float or None.
原因, MQTT 发布信息,是不能发布 对象的,只能发布 字符串,整形,浮点型这样的 解决方法 self.__mqtt__.publish("computex/iot/5100/DataTr ...
- javascrpt 代码
一.window.open关闭子页面时刷新父页面 window.opener.location.reload(); window.opener=null;window.close(); 二.AJAX返 ...
- .Net中的内存分配问题
最近在测试的时候,要求测试内存不足的情况.我不想去开很多的程序来占用内存,那样太麻烦了,也不太精确.于是就写一个小程序来占用内存,想法很简单,就是声明一个Byte数组在占用内存,没想到这么简单的想法却 ...
- jQuery&CSS 顶部和底部固定浮动工具栏 兼容IE6
http://www.cnblogs.com/lhj588/archive/2013/04/02/2994639.html —————————————————————————————————————— ...
- 在PHP中使用协程实现多任务调度
PHP5.5一个比较好的新功能是加入了对迭代生成器和协程的支持.对于生成器,PHP的文档和各种其他的博客文章已经有了非常详细的讲解.协程相对受到的关注就少了,因为协程虽然有很强大的功能但相对比较复杂, ...
- js实现选集功能
项目中有个播放列表选集的需求,如下图: 现在展示的1-42集全部,我们如何实现这个选集的功能呢? 我的思路如下: 1.将这42集按每10集划分,并存入数组: 2.保存开始和结束位置,比如说1~10,开 ...
- 目录_Java内存分配(直接内存、堆内存、Unsafel类、内存映射文件)
1.Java直接内存与堆内存-MarchOn 2.Java内存映射文件-MarchOn 3.Java Unsafe的使用-MarchOn 简单总结: 1.内存映射文件 读文件时候一般要两次复制:从磁盘 ...
- 目录_JVM专题
(PS:多为<深入理解Java虚拟机——JVM高级特性与最佳实践>一书的阅读笔记,权记于此以备忘) 纲要: 类加载(加载.连接(验证.准备.解析).初始化) (类的生命周期:除此5个外,还 ...
- The SDK platform-tools version ((23)) is too old to check APIs compiled with API 26;
好像是更新过啥SDK之后,项目一直在包名的那一行显示红线,不过是不报编译错误的,就是看着老扎心老扎心的,开始以为是指定的SDK版本的问题,修改后发现无效,最后找到方法解决: 打开SDK Manager ...