【转】Webdriver的PageObject改造By 张飞
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 "";
}
Page类实例化时初始化@FindBy注解并赋值给FindElement类将@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;
} }
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(WebElementExt.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 WebElementExt element; public void clieckButton(){
element.click();
} }
【转】Webdriver的PageObject改造By 张飞的更多相关文章
- Selenium Webdriver 的 PageObject 改造
PageObject中提供了一个@FindBy注解,也非常好用,但由于其是一次性全部初始化所有的WebElement,对于当前还不存在于页面上的Element在初始化时就会报错,为了解决这个问题,自然 ...
- [ZZ] [精彩盘点] TesterHome 社区 2018年 度精华帖
原文地址: https://testerhome.com/topics/17646 相逢即是缘分,总有一篇适合您! 感觉好的请点赞收藏 ,感觉分类不严谨的,欢迎反馈给我! 测试方法&测试管理 ...
- PageObject设计模式,在selenium自动化测试中的运用
PageObject设计模式1. Web自动化测试框架(WebTestFramework)是基于Selenium框架且采用PageObject设计模式进行二次开发形成的框架. 2. web测试时,建议 ...
- Selenium WebDriver 数据驱动测试框架
Selenium WebDriver 数据驱动测试框架,以QQ邮箱添加联系人为示例,测试框架结构如下图,详细内容请阅读吴晓华编著<Selenium WebDiver 实战宝典>: Obje ...
- PageObject设计模式 在selenium 自动化测试里面的应用
PageObject设计模式1. Web自动化测试框架(WebTestFramework)是基于Selenium框架且采用PageObject设计模式进行二次开发形成的框架. 2. web测试时,建议 ...
- python3+selenium框架设计01-Page Object
页面对象模型Page Object Modal是一种脚本设计模型,将页面元素,业务操作分割,当实际页面发生变化的时候,只需要修改页面元素文件,业务操作不需要修改. 具体实现需要先写一个页面公共类,里面 ...
- Selenium(Python)页面对象+数据驱动测试框架
整个工程的目录结构: 常用方法类: class SeleniumMethod(object): # 封装Selenium常用方法 def __init__(self, driver): self.dr ...
- Python自动化测试PO模式
页面元素定位信息 页面元素定位信息文件 [leadscloud_login] input_user_name = xpath>//*[@id='main']/div/div[2]/div[2]/ ...
- Cypress系列(62)- 改造 PageObject 模式
如果想从头学起Cypress,可以看下面的系列文章哦 https://www.cnblogs.com/poloyy/category/1768839.html PO 模式 PageObject(页面对 ...
随机推荐
- 微信小程序中的组件使用2
需求 上面两个页面是同一个小程序的不同页面,两个页面中都是用到了label,有相似的地方,但是也有不同之处,这个时候,如果我们想要将这些label做出组件,然后复用,有该怎么做呢? 基础组件 首 ...
- python之路——18
王二学习python的笔记以及记录,如有雷同,那也没事,欢迎交流,wx:wyb199594 有需要<正则指引>这本书的可以联系我,仅供学习交流使用 复习 1.递归函数,必须有结束条件2.返 ...
- consul配置参数大全、详解、总结
命令行选项 以下选项全部在命令行中指定. -advertise - 通告地址用于更改我们通告给集群中其他节点的地址.默认情况下,-bind地址是通告的.但是,在某些情况下,可能存在无法绑定的可路由地址 ...
- spring入门-注解的使用
说明: 使用注解和使用配置文件实现的功能是一样的,都是为了解耦,但是配置文件语法属于非编程语言法语,无法调试,难以定位bug,使用注解更易定位问题. 配置步骤 编译器必须先安装了STS插件 第一步 导 ...
- Linux 信号signal处理函数
转自:http://www.cnblogs.com/taobataoma/archive/2007/08/30/875662.html alarm(设置信号传送闹钟) 相关函数 signal,slee ...
- 学习excel的使用技巧复制一列文本成新列去重
学习excel的使用技巧复制一列文本成新列去重 其实比较简单的技巧 知道了就会 不知道就比较麻烦 直接复制到一列 找到 数据选项 删除重复项
- 6.3 基于二分搜索树、链表的实现的集合Set复杂度分析
两种集合类的复杂度分析 在[6.1]节与[6.2]节中分别以二分搜索树和链表作为底层实现了集合Set,在本节就两种集合类的复杂度分析进行分析:测试内容:6.1节与6.2节中使用的书籍.测试方法:测试两 ...
- AE10.0及AE10.0以上的版本调用ESRI.ArcGIS.esriSystem出现的问题
如果本地安装的是AE10.0以上,那么添加ESRI.ArcGIS.esriSystem引用时,会出现esriLicenseProductCode并不包含esriLicenseProductCodeAr ...
- XenApp6.5产品BUG
外网登录报错,手机登录报错问题解决: XenApp6.5产品BUG, 在WI服务器的两个web站点中修改defalut.ica文件中添加一行,CGPAddr=即可. 路径:C:\inetpub\www ...
- 对抗生成网络-图像卷积-mnist数据生成(代码) 1.tf.layers.conv2d(卷积操作) 2.tf.layers.conv2d_transpose(反卷积操作) 3.tf.layers.batch_normalize(归一化操作) 4.tf.maximum(用于lrelu) 5.tf.train_variable(训练中所有参数) 6.np.random.uniform(生成正态数据
1. tf.layers.conv2d(input, filter, kernel_size, stride, padding) # 进行卷积操作 参数说明:input输入数据, filter特征图的 ...