51Testing软件测试论坛

 找回密码
 (注-册)加入51Testing

QQ登录

只需一步,快速开始

微信登录,快人一步

查看: 1525|回复: 1
打印 上一主题 下一主题

[讨论] Webdriver 的 PageObject 改造

[复制链接]

该用户从未签到

跳转到指定楼层
1#
发表于 2018-3-5 14:40:24 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
PageObject中提供了一个@FindBy注解,也非常好用,但由于其是一次性全部初始化所有的
WebElement,对于当前还不存在于页面上的Element在初始化时就会报错,为了解决这个问
题,自然就不能用这个@FindBy注解了,而我们可以自已去写一个类似的注解来解决这个问
题,下面是思路的实现:

自定义一个@FindBy注解
  1. @Retention(RetentionPolicy.RUNTIME)
  2. @Target({ ElementType.FIELD })
  3. public @interface FindBy {

  4.     String name();

  5.     int age();

  6.     int lazy() default 0;
  7. }
  8. 定义一个TestInfo类来模拟WebElement类

  9. public class TestInfo {

  10.     private String name;

  11.     private int age;

  12.     public String getName() {
  13.         return name;
  14.     }

  15.     public void setName(String name) {
  16.         this.name = name;
  17.     }

  18.     public int getAge() {
  19.         return age;
  20.     }

  21.     public void setAge(int age) {
  22.         this.age = age;
  23.     }

  24.     @Override
  25.     public String toString() {
  26.         return "TestInfo [name=" + name + ", age=" + age + "]";
  27.     }

  28. }
  29. 解析@FindBy注解

  30. public class PageUtil {

  31.     private static void initialLazyInfo(Object obj, int lazy) {
  32.         try{
  33.             Field[] fields = obj.getClass().getDeclaredFields();
  34.             for (Field field : fields) {
  35.                 if(field.isAnnotationPresent(FindBy.class) && field.getType().equals(TestInfo.class)){
  36.                     FindBy findBy = field.getAnnotation(FindBy.class);
  37.                     if(findBy.lazy()==lazy){
  38.                         TestInfo temp = new TestInfo();
  39.                         temp.setName(findBy.name());
  40.                         temp.setAge(findBy.age());
  41.                         field.setAccessible(true);
  42.                         field.set(obj, temp);
  43.                     }
  44.                 }
  45.             }
  46.         }catch(Exception e){
  47.             e.printStackTrace();
  48.         }
  49.     }

  50.     public static void initialLazy(Object obj){
  51.         PageUtil.initialLazyInfo(obj, 0);
  52.     }

  53.     public static void initialLazy(Object obj, int lazy){
  54.         PageUtil.initialLazyInfo(obj, lazy);
  55.     }

  56. }
  57. 使用方式

  58. public class DemoPage {

  59.     public DemoPage() {
  60.         PageUtil.initialLazy(this);
  61.     }

  62.     @FindBy(name="zf1", age=1)
  63.     private TestInfo info1;

  64.     @FindBy(name="zf2", age=2, lazy=1)
  65.     private TestInfo info2;

  66.     public void test(){
  67.         System.out.println("info1 is: " + info1);
  68.         System.out.println("info2 is: " + info2);
  69.         PageUtil.initialLazy(this, 1);
  70.         System.out.println("info2 is: " + info2);
  71.     }

  72.     public static void main(String[] args) {
  73.         DemoPage dp = new DemoPage();
  74.         dp.test();
  75.     }

  76. }
  77. 运行结果

  78. info1 is: TestInfo [name=zf1, age=1]
  79. info2 is: null
  80. info2 is: TestInfo [name=zf2, age=2]
复制代码
说明

将TestInfo初始化进行了分层次的初始化
在需要用到的地方用PageUtil.initialLazy(this, int);进行初始化
以上虽然实现了分层次的初始化,但是在要用到的地方都需要调用PageUtil.initialLazy(this,
int);,还是显得有点麻烦,要解决这个问题,还得从改造WebElement类开始,然后自定义
一个@FindBy注解,并且在需要用到元素的地方再去判断并初始化。

定义@FindBy注解
  1. @Retention(RetentionPolicy.RUNTIME)
  2. @Target({ ElementType.FIELD })
  3. public @interface FindBy {

  4.     String id() default "";

  5.     String name() default "";

  6.     String className() default "";

  7.     String css() default "";

  8.     String tagName() default "";

  9.     String linkText() default "";

  10.     String partialLinkText() default "";

  11.     String xpath() default "";
  12. }
  13. 将@FindBy注解中的值结赋到一个中间类中去,在Page类进行初始化的时候进行赋值

  14. public class FindElement {

  15.     private String id;

  16.     private String name;

  17.     private String className;

  18.     private String css;

  19.     private String tagName;

  20.     private String linkText;

  21.     private String partialLinkText;

  22.     private String xpath;

  23.     public String getId() {
  24.         return id;
  25.     }

  26.     public void setId(String id) {
  27.         this.id = id;
  28.     }

  29.     public String getName() {
  30.         return name;
  31.     }

  32.     public void setName(String name) {
  33.         this.name = name;
  34.     }

  35.     public String getClassName() {
  36.         return className;
  37.     }

  38.     public void setClassName(String className) {
  39.         this.className = className;
  40.     }

  41.     public String getCss() {
  42.         return css;
  43.     }

  44.     public void setCss(String css) {
  45.         this.css = css;
  46.     }

  47.     public String getTagName() {
  48.         return tagName;
  49.     }

  50.     public void setTagName(String tagName) {
  51.         this.tagName = tagName;
  52.     }

  53.     public String getLinkText() {
  54.         return linkText;
  55.     }

  56.     public void setLinkText(String linkText) {
  57.         this.linkText = linkText;
  58.     }

  59.     public String getPartialLinkText() {
  60.         return partialLinkText;
  61.     }

  62.     public void setPartialLinkText(String partialLinkText) {
  63.         this.partialLinkText = partialLinkText;
  64.     }

  65.     public String getXpath() {
  66.         return xpath;
  67.     }

  68.     public void setXpath(String xpath) {
  69.         this.xpath = xpath;
  70.     }

  71. }
  72. Page类实例化时初始化@FindBy注解并赋值给FindElement类

  73. public class PageUtil {

  74.     public static void initialWebElement(Object obj) {
  75.         try{
  76.             Field[] fields = obj.getClass().getDeclaredFields();
  77.             for (Field field : fields) {
  78.                 if(field.isAnnotationPresent(FindBy.class) && field.getType().equals(WebElement.class)){
  79.                     FindBy findBy = field.getAnnotation(FindBy.class);
  80.                     FindElement findElement = new FindElement();
  81.                     if(!"".equals(findBy.id())){
  82.                         findElement.setId(findBy.id());
  83.                     }else if(!"".equals(findBy.name())){
  84.                         findElement.setName(findBy.name());
  85.                     }else if(!"".equals(findBy.className())){
  86.                         findElement.setClassName(findBy.className());
  87.                     }else if(!"".equals(findBy.css())){
  88.                         findElement.setCss(findBy.css());
  89.                     }else if(!"".equals(findBy.tagName())){
  90.                         findElement.setTagName(findBy.tagName());
  91.                     }else if(!"".equals(findBy.linkText())){
  92.                         findElement.setLinkText(findBy.linkText());
  93.                     }else if(!"".equals(findBy.partialLinkText())){
  94.                         findElement.setPartialLinkText(findBy.partialLinkText());
  95.                     }else if(!"".equals(findBy.xpath())){
  96.                         findElement.setXpath(findBy.xpath());
  97.                     }
  98.                     WebElementExt ext = new WebElementExt(findElement);
  99.                     field.setAccessible(true);
  100.                     field.set(obj, ext);
  101.                 }
  102.             }
  103.         }catch(Exception e){
  104.             e.printStackTrace();
  105.         }
  106.     }

  107. }

复制代码

分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏
回复

使用道具 举报

该用户从未签到

2#
 楼主| 发表于 2018-3-5 14:41:07 | 只看该作者
改造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();
}

}
经过上面这样改造后,即便是页面中动态加载的元素,也不用担心会报错了,也不用多次初始化了!
回复 支持 反对

使用道具 举报

本版积分规则

关闭

站长推荐上一条 /1 下一条

小黑屋|手机版|Archiver|51Testing软件测试网 ( 沪ICP备05003035号 关于我们

GMT+8, 2024-4-20 08:21 , Processed in 0.072469 second(s), 22 queries .

Powered by Discuz! X3.2

© 2001-2024 Comsenz Inc.

快速回复 返回顶部 返回列表