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 改造的更多相关文章

  1. 【转】Webdriver的PageObject改造By 张飞

    Webdriver的PageObject改造 PageObject中提供了一个@FindBy注解,也非常好用,但由于其是一次性全部初始化所有的WebElement,对于当前还不存在于页面上的Eleme ...

  2. Selenium WebDriver 数据驱动测试框架

    Selenium WebDriver 数据驱动测试框架,以QQ邮箱添加联系人为示例,测试框架结构如下图,详细内容请阅读吴晓华编著<Selenium WebDiver 实战宝典>: Obje ...

  3. 使用httpclient 调用selenium webdriver

    结合上次研究的selenium webdriver potocol ,自己写http request调用remote driver代替selenium API selenium web driver ...

  4. Selenium的PO模式(Page Object Model)|(Selenium Webdriver For Python)

            研究Selenium + python 自动化测试有近两个月了,不能说非常熟练,起码对selenium自动化的执行有了深入的认识. 从最初无结构的代码,到类的使用,方法封装,从原始函数 ...

  5. Selenium WebDriver 之 PageObjects 模式 by Example

    目录 1. 项目配置 2. 一个WebDriver简单例子 3. 使用Page Objects模式 4. 总结 5. Troubleshooting 6. 参考文档 本篇文章通过例子来阐述一下Sele ...

  6. Selenium WebDriver Code

    Selenium WebDriver 用于模拟浏览器的功能,可以做网站测试用,也可以用来做crawler.我是用eclipse开发的,导入selenium-server-standalone-***. ...

  7. selenium webdriver 右键另存为下载文件(结合robot and autoIt)

    首先感谢Lakshay Sharma 大神的指导 最近一直在研究selenium webdriver右键菜单,发现selenium webdriver 无法操作浏览器右键菜单,如图 如果我想右键另存为 ...

  8. Selenium Webdriver java 积累一

    Selenium Webdriver 学习: http://jarvi.iteye.com/category/203994 https://github.com/easonhan007/webdriv ...

  9. Selenium Webdriver下click失效问题解决

    最近在使用Selenium Webdriver(Selenium2.0)进行界面自动化测试的时候发现单击事件无效,通过driver.findElement的方式是可以找到click元素的,但是就是cl ...

随机推荐

  1. Linux使用redis

    在linux遇到这种情况. 注意,这里本redis 用的端口是6389 通过 ps -aux 看到redis 启动了: root ? Ssl Jun14 : redis-server *: root ...

  2. 【转】全Javascript的Web开发架构:MEAN和Yeoman【译】

    引言 最近在Angular社区的原型开发者间,一种全Javascript的开发架构MEAN正突然流行起来.其首字母分别代表的是:(M)ongoDB——noSQL的文档数据库,使用JSON风格来存储数据 ...

  3. 解释#ifdef ALLOC_PRAGMA代码段的原理

    By default, the kernel loader will load all driver executables and any global data that you may have ...

  4. js 控制输入文字个数(换行不算)

    如题,换行符在textarea中是要当成一个字符的.用普通的maxlength属性就不行了,于是想到通过事件来控制输入文字的长度. 注意哦,回车换行不能算成字符.这样的话,普通的substring等方 ...

  5. 小措施提高Linux服务器安全

    禁止root远程登录 作为默认系统管理账号root是最容易攻击的目标.禁止通过ssh远程登录是绝对必须的. 方法: 编辑 /etc/ssh/sshd_config PermitRootLogin no ...

  6. PCL关键点(1)

    关键点也称为兴趣点,它是2D图像或是3D点云或者曲面模型上,可以通过定义检测标准来获取的具有稳定性,区别性的点集,从技术上来说,关键点的数量相比于原始点云或图像的数据量减小很多,与局部特征描述子结合在 ...

  7. Map总结(HashMap, Hashtable, TreeMap, WeakHashMap等使用场景)

    概要 学完了Map的全部内容,我们再回头开开Map的框架图. 本章内容包括:第1部分 Map概括第2部分 HashMap和Hashtable异同第3部分 HashMap和WeakHashMap异同 转 ...

  8. 无法加载 Parallels 驱动器

    解决 最新版 mac 系统 无法使用未签名第三驱动 10.12.多 我的情况是 10.11.4 Beta (15E27e) 使用绿联usb网卡不正常. 下面的命令为检测驱动是否装载的一些命令.sudo ...

  9. Ubuntu下qemu环境搭建

    在查找资料过程中,发现自己搭建虚拟的arm环境的话,有一个比较好的软件就是qemu了,当然还有其他的,大家各投所好就好. 接下来说一下qemu环境搭建过程. 其实搭建很简单,作为小白,我还是捣鼓了两三 ...

  10. USB学习笔记连载(十二):USB描述符

    USB设备是端口,接口,配置的集合,USB协议是以各种USB描述符来表征USB设备的功能.计算机通过这些描述符来获得USB设备的功能. USB描述符包括: USB标准设备描述符,USB集线器描述符.H ...