有很多团队使用Python + selenium + robotframework做自动化测试,好处是不用造“轮子”,缺点是不利于测试人员的职业发展,人工智能都火爆了,我们测试当然要注重提升自身的能力。当然robotframework给我们提供了一个很好的理念:案例分层测试,使用抽象与封装,把一个实现过程分成不同多层。提高的灵活性,从而达到可扩展性和可维护性。
下面简单介绍环境搭建和着重介绍我们测试过程中遇到的问题,希望能帮到一些测试同学。
一、环境搭建:
1)安装32位的1.8的jdk,并配置环境变量。CLASSPATH=.;%JAVA_HOME%\lib\dt.jar;%JAVA_HOME%\lib\tools.jar
JAVA_HOME=D:\Program Files\Java\jdk1.8
PATH=%JAVA_HOME%\bin
2)下载testng离线安装testng插件(因为公司网络限制,无法在线安装testng插件),将features文件夹的jar包拷贝到eclipse的features文件夹内,将plugins文件夹的jar包拷贝到plugins文件夹里,然后重启eclipse,验证是否安装成功。
3)网上下载selenium-java-2.53.0,引入到工程里。
4)下载浏览器驱动,注意:必须得是32位的,否则会出现64位系统下执行非常慢的问题。当然得配置环境变量,否则无法启动浏览器。
二、认识常见的定位方式:常见的定位方式有id、name、链接的全部文字定位、链接的部分文字定位、XPath定位、CSS定位、class名称定位、tagName定位、jQuery定位。语法如下:WebDriver driver;
JavascriptExecutor js;
WebElement element = driver.findElement(By.id("ID值"));//ID定位
WebElement element = driver.findElement(By.name("name值"));//name定位WebElement element =driver.findElement(By.linkText("链接的全部文字内容"));
WebElement element =driver.findElement(By.partialLinkText("链接的部分文字内容"));
WebElement element =driver.findElement(By.xpath("//span[contains(text(), '确定')]"));//xpath定位的一个例子
WebElement element =driver.findElement(By.cssSelector("#gfxftd > span > input.combo-text"));//CSS定位的一个例子
WebElement element = driver.findElement(By.className("页面的class属性值"));
WebElement element = driver.findElement(By.tagName("页面中的HTML标签名称"));
js = (JavascriptExecutor )driver;
WebElement element=(WebElement)js.executeScript("jQuery定位表达式"); //调用jQuery库从查找功能
以下是xpath的定位介绍:
第一种方法:通过绝对路径做定位(相信大家不会使用这种方式)
By.xpath("html/body/div/form/input")第二种方法:通过相对定位
By.xpath("//input")
第三种方法:通过元素索引定位
By.xpath("//input[4]")
第四种方法:使用xpath属性定位(结合第2、第3中方法可以使用)
By.xpath("//input[@id='kw1']")
By.xpath("//input[@type='name' and @name='kw1']")
第五种方法:使用部分属性值匹配(最强大的方法)
By.xpath("//input[start-with(@id,'nice')
By.xpath("//input[ends-with(@id,'很漂亮')
By.xpath("//input[contains(@id,'那么美')]") //税务组大量使用这种方式以下是税务组使用部分属性匹配的一个例子
driver.switchTo().frame(driver.findElement(By.xpath("//iframe[contains(@src,'/vatmgr/saleInvoice/invoiceRed/special/create.jsp')]")));
以下是tagName的一个例子 List<WebElement> allInputs = driver.findElements(By.tagName("input"));
三、自动化测试中常见的问题:
1)NoSuchElementException: Unable to find element with xpath
字面意思很简单,使用xpath找不到元素。原因是定位不正确或是速度太快,元素或页面还没有加载完。
解决办法:
a) 先确定定位是否正确;
b)若定位正确,加一个等待。常用的等待有 显示等待 > 隐式等待 > Thread.sleep()
显示等待使用语法如下:
//设定一个阈值150秒。只有满足显示等待的条件要求,测试代码才会继续向后执行后续的测试逻辑。当显示等待条件未被满足的时候,在设定的最大显示等待时间阈值内,会停留在当前代码位置等待,直到设定的等待条件被满足,才会继续执行后续的测试逻辑。如果超过设定的最大显示等待时间阈值,则测试程序会抛出异常,测试用例被认为执行失败。
WebDriverWait wt = new WebDriverWait(driver,150)//设置显示等待最长等待时间为150秒,用于显示等待
wt.until(ExpectedConditions.presenceOfElementLocated(By.xpath("//div[.='平安健康保险股份有限公司广东分公司']"))).click();//页面元素在页面中存在,我们税务组目前只用到这一种显示等待
页面元素是否被选中,例如单选复选框,可以使用 elementToBeSelected(By locator)
页面元素是否包含特定的文本,可以使用 textToBePresentInElement(By locator)
隐式等待语法如下:
//不推荐使用,缺点是设定了等待时长,则在页面元素没有被立即找到的情况下,测试程序也必须等待设定的时长。例如,设定了隐式等待时间为10秒,即使页面元素在过了5秒后显示了,测试程序也会等待10秒后再进行页面元素的查找工作
driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS);
c)实际应用可能使用显示等待也无法找到元素,这时就要靠自己写代码来处理,我们税务组是这样处理的:
WebElement sr = null;
while(null == sr) {
try {
sr = driver.findElement(By.cssSelector("#gfxftd > span > input.combo-text"));
} catch (Exception e) {
// TODO: handle exception
continue;
}
}
sr.sendKeys("平安健康保险股份有限公司广东分公司");
这里使用while循环来代替等待,因为系统不稳定,也是不得已而为之,出现异常了,依然让它循环,直到找到为止。
2)NullPointerException:空指针异常
出现空指针异常的原因必定是出现了null,出现null的情况多为:类没有初始化就直接使用;参数在传递过程中,没有正确传递过来导致后续被调用方法中接受到的参数实际为null;
出现这种异常,就检查类有没初始化,若初始化了还报空指针,就一定是元素没找着,解决方法:还是使用上面写的while循环。
3)iframe的处理:
iframe是嵌套的页面,必须使用driver.switchTo().frame处理,以下是一段代码
driver.switchTo().defaultContent();//由上个iframe切出
driver.switchTo().frame(driver.findElement(By.xpath("//iframe[contains(@src,'/vatmgr/saleInvoice/invoiceRed/special/create.jsp')]")));
遇到多个iframe就需要确定iframe的位置,若是嵌套就需要多次使用driver.switchTo().frame,注意iframe里的操作完成后,需要切回原页面,就需要使用driver.switchTo().defaultContent(),可能需要多次使用,这取决于iframe嵌套了几层,若是两层,就需要使用两次。
4)找到元素,但是无法点击,这种情况比较普遍:我们使用JS来点击元素
//这里有时找不到,我使用下面的JS来代替一般元素定位按钮点击新增按钮
JavascriptExecutor js = (JavascriptExecutor) driver;
js.executeScript("arguments[0].click();",
driver.findElement(By.id("matterAdd")));
5)表格的处理:将页面所有的input框找到放到一个list里,然后遍历判断。
//得到第一条单选框,定位标签,然后判断,找到第2个checkbox
List<WebElement> allInputs = driver.findElements(By.tagName("input"));
WebElement wb=null;
int i=0;
for(WebElement e: allInputs){
System.out.println(e.getAttribute("type"));
if (e.getAttribute("type").equals("checkbox")){
if(i==1){
System.out.println(e.getText().toString());
wb=e;
break;
}
i++;
}
}
if(wb!=null){
wb.click();
}
6)封装逻辑:有的时候webdriver的API无法满足我们的需求,这个时候就需要自己封装实现。webdriver中有个WebDriverWait对象,以下是封装的显示等待的一个例子
//封装显示等待
public static WebElement webelementExplicitWait(WebDriver driver,By by){
return (new WebDriverWait(driver, 10)) .until(
new ExpectedCondition< WebElement>(){
@Override
public WebElement apply(WebDriver d) {
return d.findElement(by);
}
}
)
}
以上代码是时间写死了,可重写以上方法,多传一个时间参数
public static WebElement webelementExplicitWait(WebDriver driver, By by, int second ){
return (new WebDriverWait(driver, second)) .until(
new ExpectedCondition< WebElement>(){
@Override
public WebElement apply(WebDriver d) {
return d.findElement(by);
}
}
)
}
这种写法好像测试工程师看起来费劲,而且没有捕获异常,修改成以下代码:
public static WebElement webelementExplicitWait(WebDriver driver, By by, int second ){
WebElement waitElement = null;
WebDriverWait wait = new WebDriverWait(driver, second);
//以下用于捕获异常
try{
waitElement = wait.until(new ExpectedCondition<WebElement>(){
public WebElement apply(WebDriver d) {
return d.findElement(by);
} })
}catch(Exception e){
System.out.println(by.toString() + " is not exist until " + second);
}
return waitElement; //返回waitElement对象
}
转载于:https://my.oschina.net/u/3680584/blog/1537184