元素对象管理:
元素对象(以下称为locator)的维护与管理很麻烦,因为locator比较多,每个页面上要操作的可能有几十个,如何快速的查找及维护好能够使我们写脚本的速度及维护速度大大提升。在前端开发中,开发人员通常是把UI样式放在CSS文件中,受此影响,我们也可以把我们的locator放在一个专门的文件中,按照页面来分类,提取其公共的locator放在公共的文件中,这样或许可以提升些许编写脚本速度及后期维护成本,效果就是如果UI变了,我们只需要修改对应的页面中的locator就行了,脚本都不需要重新编译(如果是用需要编译的语言,如JAVA),下面我将介绍一下如何放在专门的文件中,如何解析该文件,及在脚本中如何调用。下面的脚本语言为JAVA。
1 import org.ho.yaml.Yaml; 2 import java.io.File; 3 import java.io.FileInputStream; 4 import java.io.FileNotFoundException; 5 import java.util.HashMap; 6 7 public class Demo { 8 9 private String yamlFile; 10 11 public Demo() { 12 yamlFile = "demo"; 13 this.getYamlFile(); 14 } 15 16 private HashMap<String, HashMap<String, String>> ml; 17 18 @SuppressWarnings("unchecked") 19 public void getYamlFile() { 20 File f = new File("locator/" + yamlFile + ".yaml"); 21 try { 22 ml = Yaml.loadType(new FileInputStream(f.getAbsolutePath()), 23 HashMap.class); 24 } catch (FileNotFoundException e) { 25 e.printStackTrace(); 26 } 27 } 28 }
可以在本地创建一个TestBaidu.yaml文件,保存在locator目录中,locator与src同级目录,然后写个main方法来调用一个getYamlFile方法,可以看到解析TestBaidu.yaml后的值都赋给了变量ml。解析过程如此简单,解析速度如此之快,yaml文件也比较直观,这是我选择用yaml文件的原因,当然可能还有其它更好的选择,大家可以自行尝试。
1 private By getBy(String type, String value) { 2 By by = null; 3 if (type.equals("id")) { 4 by = By.id(value); 5 } 6 if (type.equals("name")) { 7 by = By.name(value); 8 } 9 if (type.equals("xpath")) { 10 by = By.xpath(value); 11 } 12 if (type.equals("className")) { 13 by = By.className(value); 14 } 15 if (type.equals("linkText")) { 16 by = By.linkText(value); 17 } 18 return by; 19 }
这样通过ml中的type与value的值就对产生一个By对象。
1 import org.ho.yaml.Yaml; 2 import org.openqa.selenium.By; 3 import org.openqa.selenium.WebDriver; 4 import org.openqa.selenium.WebElement; 5 6 import java.io.File; 7 import java.io.FileInputStream; 8 import java.io.FileNotFoundException; 9 import java.util.HashMap; 10 11 public class Demo { 12 13 private String yamlFile; 14 public WebDriver driver; 15 16 public Demo() { 17 driver = DriverInstance.getInstance(); 18 yamlFile = "demo"; 19 this.getYamlFile(); 20 } 21 22 private HashMap<String, HashMap<String, String>> ml; 23 24 @SuppressWarnings("unchecked") 25 public void getYamlFile() { 26 File f = new File("locator/" + yamlFile + ".yaml"); 27 try { 28 ml = Yaml.loadType(new FileInputStream(f.getAbsolutePath()), 29 HashMap.class); 30 } catch (FileNotFoundException e) { 31 e.printStackTrace(); 32 } 33 } 34 35 private By getBy(String type, String value) { 36 By by = null; 37 if (type.equals("id")) { 38 by = By.id(value); 39 } 40 if (type.equals("name")) { 41 by = By.name(value); 42 } 43 if (type.equals("xpath")) { 44 by = By.xpath(value); 45 } 46 if (type.equals("className")) { 47 by = By.className(value); 48 } 49 if (type.equals("linkText")) { 50 by = By.linkText(value); 51 } 52 return by; 53 } 54 55 public WebElement getElement(String key) { 56 String type = ml.get(key).get("type"); 57 String value = ml.get(key).get("value"); 58 return driver.findElement(this.getBy(type, value)); 59 } 60 61 public static void main(String[] args){ 62 Demo d = new Demo(); 63 WebElement element = d.getElement("baidu_input"); 64 element.sendKeys(""); 65 } 66 }
1 private WebElement watiForElement(final By by) { 2 WebElement element = null; 3 int waitTime = Integer.parseInt(Config.getConfig("waitTime")); 4 try { 5 element = new WebDriverWait(driver, waitTime) 6 .until(new ExpectedCondition<WebElement>() { 7 public WebElement apply(WebDriver d) { 8 return d.findElement(by); 9 } 10 }); 11 } catch (Exception e) { 12 System.out.println(by.toString() + " is not exist until " + waitTime); 13 } 14 return element; 15 }
于是乎getElement方法里面就可以改为
1 public WebElement getElement(String key) { 2 String type = ml.get(key).get("type"); 3 String value = ml.get(key).get("value"); 4 return this.watiForElement(this.getBy(type, value)); 5 }
1 private boolean waitElementToBeDisplayed(final WebElement element) { 2 boolean wait = false; 3 if (element == null) 4 return wait; 5 try { 6 wait = new WebDriverWait(driver, Integer.parseInt(Config 7 .getConfig("waitTime"))) 8 .until(new ExpectedCondition<Boolean>() { 9 public Boolean apply(WebDriver d) { 10 return element.isDisplayed(); 11 } 12 }); 13 } catch (Exception e) { 14 System.out.println(element.toString() + " is not displayed"); 15 } 16 return wait; 17 }
如此一来,getElement方法又可以改进一下了。
1 public WebElement getElement(String key) { 2 String type = ml.get(key).get("type"); 3 String value = ml.get(key).get("value"); 4 WebElement element = this.watiForElement(this.getBy(type, value)); 5 if(!this.waitElementToBeDisplayed(element)) 6 element = null; 7 return element; 8 }
1 public boolean waitElementToBeNonDisplayed(final WebElement element) { 2 boolean wait = false; 3 if (element == null) 4 return wait; 5 try { 6 wait = new WebDriverWait(driver, Integer.parseInt(Config 7 .getConfig("waitTime"))) 8 .until(new ExpectedCondition<Boolean>() { 9 public Boolean apply(WebDriver d) { 10 return !element.isDisplayed(); 11 } 12 }); 13 } catch (Exception e) { 14 System.out.println("Locator [" + element.toString() 15 + "] is also displayed"); 16 } 17 return wait; 18 }
1 public WebElement getElementNoWait(String key) { 2 WebElement element = null; 3 String type = ml.get(key).get("type"); 4 String value = ml.get(key).get("value"); 5 try{ 6 element = driver.findElement(this.getBy(type, value)); 7 }catch(Exception e){ 8 element = null; 9 } 10 return element; 11 }
1 private WebElement getLocator(String key, boolean wait) { 2 WebElement element = null; 3 if (ml.containsKey(key)) { 4 HashMap<String, String> m = ml.get(key); 5 String type = m.get("type"); 6 String value = m.get("value"); 7 By by = this.getBy(type, value); 8 if (wait) { 9 element = this.watiForElement(by); 10 boolean flag = this.waitElementToBeDisplayed(element); 11 if (!flag) 12 element = null; 13 } else { 14 try { 15 element = driver.findElement(by); 16 } catch (Exception e) { 17 element = null; 18 } 19 } 20 } else 21 System.out.println("Locator " + key + " is not exist in " + yamlFile 22 + ".yaml"); 23 return element; 24 }
再把getElement与getElementNoWait方法进行修改
1 public WebElement getElement(String key) { 2 return this.getLocator(key, true); 3 } 4 5 public WebElement getElementNoWait(String key) { 6 return this.getLocator(key, false); 7 }
1 baidu_input: 2 type: id 3 value: "%s%s" 4 baidu_button: 5 type: id 6 value: "%s"
在这里面的参数用%s来表示,于是在脚本中,我们调用getElement与getElementNoWait方法时需要我们把value给传进去,我们再来处理下这部分,增加一个方法。
1 private String getLocatorString(String locatorString, String[] ss) { 2 for (String s : ss) { 3 locatorString = locatorString.replaceFirst("%s", s); 4 } 5 return locatorString; 6 }
在上面的方法中,我们可以看到,对于value值,我们是通过一个数组循环的去替代里面的%s,再把该方法结合到getLocator方法中去。
1 private WebElement getLocator(String key, String[] replace, boolean wait) { 2 WebElement element = null; 3 if (ml.containsKey(key)) { 4 HashMap<String, String> m = ml.get(key); 5 String type = m.get("type"); 6 String value = m.get("value"); 7 if (replace != null) 8 value = this.getLocatorString(value, replace); 9 By by = this.getBy(type, value); 10 if (wait) { 11 element = this.watiForElement(by); 12 boolean flag = this.waitElementToBeDisplayed(element); 13 if (!flag) 14 element = null; 15 } else { 16 try { 17 element = driver.findElement(by); 18 } catch (Exception e) { 19 element = null; 20 } 21 } 22 } else 23 System.out.println("Locator " + key + " is not exist in " + yamlFile 24 + ".yaml"); 25 return element; 26 }
可以看到getLocator方法的参数变了,于是要重新的更改getElement与getElementNoWait方法,同时重载这两个方法。
1 public WebElement getElement(String key) { 2 return this.getLocator(key, null, true); 3 } 4 5 public WebElement getElementNoWait(String key) { 6 return this.getLocator(key, null, false); 7 } 8 9 public WebElement getElement(String key, String[] replace) { 10 return this.getLocator(key, replace, true); 11 } 12 13 public WebElement getElementNoWait(String key, String[] replace) { 14 return this.getLocator(key, replace, false); 15 }
1 baidu_input: 2 type: xpath 3 value: "//div[@id=‘%productId%‘]//div" 4 baidu_button: 5 type: xpath 6 value: "//div[@id=‘%productId%‘]//input[@name=‘button‘]"
类似于上面这种,整个里面都含有productId, 于是我们可以通过一个方法,调用这个方法后,里面的都会被替换掉,该方法如下。
1 public void setLocatorVariableValue(String variable, String value){ 2 Set<String> keys = ml.keySet(); 3 for(String key:keys){ 4 String v = ml.get(key).get("value").replaceAll("%"+variable+"%", value); 5 ml.get(key).put("value",v); 6 } 7 }
1 private HashMap<String, HashMap<String, String>> extendLocator; 2 @SuppressWarnings("unchecked") 3 public void loadExtendLocator(String fileName){ 4 File f = new File("locator/" + fileName + ".yaml"); 5 try { 6 extendLocator = Yaml.loadType(new FileInputStream(f.getAbsolutePath()), 7 HashMap.class); 8 ml.putAll(extendLocator); 9 } catch (FileNotFoundException e) { 10 e.printStackTrace(); 11 } 12 }
1 public class Locator { 2 3 private String yamlfile; 4 private WebDriver driver; 5 6 private Map<String,Map<String,String>> ml; 7 8 public Locator(WebDriver driver) 9 { 10 yamlfile="TestBaidu"; 11 this.getYamlFile(); 12 this.driver=driver; 13 } 14 15 @SuppressWarnings("unchecked") 16 public void getYamlFile() 17 { 18 File f=new File("locator/"+yamlfile+".yaml"); 19 try{ 20 ml=Yaml.loadType(new FileInputStream(f.getAbsolutePath()),HashMap.class); 21 }catch(FileNotFoundException e) 22 { 23 e.printStackTrace(); 24 } 25 } 26 27 private By getBy(String type,String value) 28 { 29 By by =null; 30 if(type.equals("id")){ 31 by=By.id(value); 32 } 33 if(type.equals("xpath")){ 34 by=By.xpath(value); 35 } 36 return by; 37 } 38 39 private boolean waitElementToBeDisplay(final WebElement element){ 40 boolean wait=false; 41 if(element ==null) 42 return wait; 43 try{ 44 wait=new WebDriverWait(driver,config.waitTime).until(new ExpectedCondition<Boolean>() 45 { 46 public Boolean apply(WebDriver d){ 47 return element.isDisplayed(); 48 } 49 }); 50 }catch(Exception e){ 51 System.out.println(element.toString()+"is not displayed"); 52 } 53 return wait; 54 } 55 56 public WebElement getElement(String key) 57 { 58 //下面三种写法公用,但重构Loactor后不用 59 // String type=ml.get(key).get("type"); 60 // String value=ml.get(key).get("value"); 61 62 //无等待时的写法 63 //return driver.findElement(this.getBy(type,value)); 64 65 //有等待时的写法 66 //return this.waitForElement(this.getBy(type,value)); 67 68 //对元素的可见不可见进行判断的写法 69 // WebElement element; 70 // element=this.waitForElement(this.getBy(type, value)); 71 // if(!this.waitElementToBeDisplay(element)) 72 // element=null; 73 // return element; 74 75 //对Locator重构之后 76 return this.getLocator(key,null,true); 77 } 78 79 //getElement多态 80 public WebElement getElement(String key,String[] replace) 81 { 82 return this.getLocator(key,replace,true); 83 } 84 85 private WebElement waitForElement(final By by) 86 { 87 WebElement element=null; 88 int waitTime=config.waitTime; 89 try{ 90 element=new WebDriverWait(driver,waitTime).until(new ExpectedCondition<WebElement>() 91 { 92 public WebElement apply(WebDriver d){ 93 return d.findElement(by); 94 } 95 }); 96 } 97 catch(Exception e){ 98 System.out.println(by.toString()+"is not exist until"+waitTime); 99 } 100 return element; 101 102 } 103 104 //等待对象消失的方法 105 @SuppressWarnings("unused") 106 private boolean waitElementToBeNonDisplay(final WebElement element){ 107 boolean wait=false; 108 if(element ==null) 109 return wait; 110 try{ 111 wait=new WebDriverWait(driver,config.waitTime).until(new ExpectedCondition<Boolean>() 112 { public Boolean apply(WebDriver d){ 113 return !element.isDisplayed(); 114 } 115 }); 116 } 117 catch(Exception e){ 118 System.out.println(element.toString()+"is also displayed"); 119 } 120 return wait; 121 } 122 123 public WebElement getElementNoWait(String key) 124 { 125 //对Locator重构之前的做法 126 // WebElement element; 127 // String type=ml.get(key).get("type"); 128 // String value=ml.get(key).get("value"); 129 // try{ 130 // element=driver.findElement(this.getBy(type, value)); 131 // } 132 // catch(Exception e){ 133 // element=null; 134 // } 135 // return element; 136 137 //对Locator重构之后 138 return this.getLocator(key,null,false); 139 } 140 141 public WebElement getElementNoWait(String key,String[] replace) 142 { 143 return this.getLocator(key,replace,false); 144 } 145 146 //因为getElment和getElementNoWait方法非常接近,可以将上述两方法合并,对Locator方法重构 147 private WebElement getLocator(String key,String[] replace,boolean wait) 148 { 149 WebElement element=null; 150 if(ml.containsKey(key)){ 151 Map<String,String> m=ml.get(key); 152 String type=m.get("type"); 153 String value=m.get("value"); 154 if(replace!=null) 155 value=this.getLocatorString(value, replace); 156 By by=this.getBy(type,value); 157 if(wait){ 158 element=this.waitForElement(by); 159 boolean flag=this.waitElementToBeDisplay(element); 160 if(!flag) 161 element=null; 162 else 163 try{ 164 element=driver.findElement(by); 165 } 166 catch(Exception e) 167 { 168 element=null; 169 } 170 } 171 } 172 else 173 { 174 System.out.println("Locator"+key+"is not exist in"+yamlfile+".yaml"); 175 return element; 176 } 177 return element; 178 } 179 180 private String getLocatorString(String locatorString,String[] ss) 181 { 182 for(String s:ss){ 183 locatorString=locatorString.replaceFirst("%s",s); 184 } 185 return locatorString; 186 } 187 188 189 /** 190 * @param args 191 */ 192 public static void main(String[] args) { 193 // TODO Auto-generated method stub 194 String[] replace={"id","kw"}; 195 SeleniumDriver selenium=new SeleniumDriver(); 196 WebDriver driver=selenium.getDriver(); 197 Locator l=new Locator(driver); 198 driver.navigate().to("http://www.baidu.com"); 199 WebElement element=l.getElement("baidu_input"); 200 element=l.getElement("baidu_input",replace); 201 element.sendKeys("aa"); 202 203 } 204 205 }
原文:http://www.cnblogs.com/leoliyue/p/4884886.html