1. 基于对象的测试
1.1 Selenium 2构成
Selenium 2是一种用于Web应用程序的自动测试工具,它提供了一套友好的API,自身就是一套类库,不依赖于任何测试框架,不需要启动其他进程或安装其他程序,也不用像Selenium 1那样需要先启动服务。
Selenium 2针对各个浏览器而开发,它取代了嵌入到被测Web应用中的JavaScript,与浏览器紧密集成,支持创建更高级的测试,避免JavaScript安全模型限制,除此之外,Selenium 2还利用操作系统级的调用模拟用户输入。WebDriver支持Firefox、IE、Opera、Chrome,还支持Android和iPhone的移动应用测试。
1.2 基于对象
Selenium 2与Selenium 1存在明显差异,尽管它们都属于浏览器自动化的API,但对于用户来说,Selenium 1提供的更多的是基于方法的API,所有方法都一个类中开放,而Selenium 2的API则面向对象,不同的对象拥有不同的操作方法,例如:
#Selenium 1 public class Main { public static void main(String[] args) { DefaultSelenium selenium = new DefaultSelenium("localhost", 4444, "*iexplore", "http://www.baidu.com"); selenium.start(); selenium.open("selenium.typeKeys(@"//input[@id='kw']","Tester"); selenium.click(@"//input[@id='su']"); } }
#Selenium 2 public class Main { public static void main(String[] args) { WebDriver driver = new FirefoxDriver(); Navigation navigation = driver.navigate(); navigation.to("http://www.baidu.com"); WebElement keyword = driver.findElement(By.id("kw")); WebElement search = driver.findElement(By.id("su")); keyword.sendKeys("Tester"); search.click(); } }
1.3 选择浏览器
要开始测试前,首先得创建Selenium的实例,也就是对应的Driver,对于Firefox、IE、Chrome,只需在电脑中安装相应的浏览器就可以开始测试了。而对于Android和iPhone,它们在测试前需要安装支持软件,以Firefox为例,例如:
public class Main { public static void main(String[] args) { WebDriver driver = new FirefoxDriver(); } }
2. 开始测试
2.1 浏览器导航对象
在Selenium 2中,要导航页面,需要用到Navigation对象,可以通过WebDriver的navigate()方法获得Navigation对象实例,例如:
public class Main { public static void main(String[] args) { WebDriver driver = new FirefoxDriver(); Navigation navigation = driver.navigate(); } }
在获得该对象后,就可以执行跳转到指定URL、前进、后退、刷新页面等操作。在JAVA中,可以使用to()来进行跳转,只需将URL作为参数即可,例如:
public class Main { public static void main(String[] args) { WebDriver driver = new FirefoxDriver(); Navigation navigation = driver.navigate(); navigation.to("http://www.baidu.com"); } }
在浏览器上,可以按前进和后退按钮来进行导航,通过back()/forward()方法,也可以实现这种导航功能,例如:
public class Main { public static void main(String[] args) { WebDriver driver = new FirefoxDriver(); Navigation navigation = driver.navigate(); navigation.to("http://www.baidu.com"); navigation.to("http://www.google.com.hk"); navigation.back(); navigation.forward(); } }
使用refresh()方法将刷新整个页面,例如:
public class Main { public static void main(String[] args) { WebDriver driver = new FirefoxDriver(); Navigation navigation = driver.navigate(); navigation.to("http://www.baidu.com"); navigation.refresh(); } }
2.2 查找条件对象
在对页面上元素操作之前,需要找到相应的元素,可以使用查找条件对象By进行查找。查找可以按照HTML元素的ID或Name属性进行,或按照HTML标签,其中最常使用的是查找ID属性,例如:
public class Main { public static void main(String[] args) { WebDriver driver = new FirefoxDriver(); Navigation navigation = driver.navigate(); navigation.to("http://www.baidu.com"); WebElement search = driver.findElement(By.id("su")); } }
与ID类似,name()方法按照Name进行查找,例如:
public class Main { public static void main(String[] args) { WebDriver driver = new FirefoxDriver(); Navigation navigation = driver.navigate(); navigation.to("http://www.baidu.com"); WebElement search = driver.findElement(By.name("wd")); } }
linkText()方法按链接文本进行查找,而partialLinkText()方法按链接文本进行模糊查找,例如:
public class Main { public static void main(String[] args) { WebDriver driver = new FirefoxDriver(); Navigation navigation = driver.navigate(); navigation.to("http://www.baidu.com"); WebElement login1 = driver.findElement(By.linkText("登录")); WebElement login2 = driver.findElement(By.partialLinkText("登录")); } }
className()方法按元素的class属性进行查找,tagName()则按标记名称进行查找并返回第一个匹配项,例如:
public class Main { public static void main(String[] args) { WebDriver driver = new FirefoxDriver(); Navigation navigation = driver.navigate(); navigation.to("http://www.baidu.com"); WebElement keyword1 = driver.findElement(By.className("s_ipt")); WebElement keyword2 = driver.findElement(By.tagName("input")); } }
如果以上方法都无法定位,可以按xpath()进行查找,例如:
public class Main { public static void main(String[] args) { WebDriver driver = new FirefoxDriver(); Navigation navigation = driver.navigate(); navigation.to("http://www.baidu.com"); WebElement search = driver.findElement(By.xpath("//input[@id='su']")); } }
2.3 操作页面元素
可以通过WebDriver的findElement()方法获得WebElement的对象实例,在获取页面元素后,就可以对该页面元素进行各种操作了。
click()方法用于执行单击元素的操作,sendKeys()方法用于给input元素输入文本,例如:
public class Main { public static void main(String[] args) { WebDriver driver = new FirefoxDriver(); Navigation navigation = driver.navigate(); navigation.to("http://www.baidu.com"); WebElement keyword = driver.findElement(By.id("kw")); WebElement search = driver.findElement(By.id("su")); keyword.sendKeys("Tester"); search.click(); } }
clear()方法用于清空input元素的值,例如:
public class Main { public static void main(String[] args) { WebDriver driver = new FirefoxDriver(); Navigation navigation = driver.navigate(); navigation.to("http://www.baidu.com"); WebElement keyword = driver.findElement(By.id("kw")); keyword.sendKeys("Tester"); keyword.clear(); } }
submit()方法用于对指定元素所在的form元素进行提交操作,例如:
public class Main { public static void main(String[] args) { WebDriver driver = new FirefoxDriver(); Navigation navigation = driver.navigate(); navigation.to("http://www.baidu.com"); WebElement keyword = driver.findElement(By.id("kw")); WebElement search = driver.findElement(By.id("su")); keyword.sendKeys("Tester"); keyword.submit(); } }
2.4 获取页面及页面元素内容
在跳转到某个页面或获取某个页面元素之后,除了对其进行操作,还可以获取它的内容。比如getTitle()方法用于返回当前网页的标题,getCurrentUrl()方法用于获取当前网页的URL,例如:
public class Main { public static void main(String[] args) { WebDriver driver = new FirefoxDriver(); Navigation navigation = driver.navigate(); navigation.to("http://www.baidu.com"); String title = driver.getTitle(); String url = driver.getCurrentUrl(); } }
getText()方法用于存储某个元素的文本值,例如链接、纯文本等,例如:
public class Main { public static void main(String[] args) { WebDriver driver = new FirefoxDriver(); Navigation navigation = driver.navigate(); navigation.to("http://www.baidu.com"); WebElement link = driver.findElement(By.name("tj_login")); String text = link.getText(); } }
isSelected()方法用于存储复选框或单选框的勾选情况,返回值为true或false,例如:
public class Main { public static void main(String[] args) { WebDriver driver = new FirefoxDriver(); Navigation navigation = driver.navigate(); navigation.to("http://www.baidu.com"); WebElement link = driver.findElement(By.name("tj_login")); link.click(); WebElement checkbox = driver.findElement(By.id("TANGRAM__PSP_8__memberPass")); boolean isSelected = checkbox.isSelected(); } }
getTagName()方法用于获取元素的标记名称,例如:
public class Main { public static void main(String[] args) { WebDriver driver = new FirefoxDriver(); Navigation navigation = driver.navigate(); navigation.to("http://www.baidu.com"); WebElement link = driver.findElement(By.name("tj_login")); String tagName = link.getTagName(); } }
isEnabled()方法用于存储input等元素的可编辑状态,isDisplayed()方法用于验证元素是否在页面上显示,例如:
public class Main { public static void main(String[] args) { WebDriver driver = new FirefoxDriver(); Navigation navigation = driver.navigate(); navigation.to("http://www.baidu.com"); WebElement keyword = driver.findElement(By.id("kw")); boolean isEnabled = keyword.isEnabled(); boolean isDisplayed = keyword.isDisplayed(); } }
getAttribute()方法用于获取指定属性的值,例如:
public class Main { public static void main(String[] args) { WebDriver driver = new FirefoxDriver(); Navigation navigation = driver.navigate(); navigation.to("http://www.baidu.com"); WebElement keyword = driver.findElement(By.id("kw")); String value = keyword.getAttribute("value"); } }
3. 测试处理
3.1 弹出对话框处理
JavaScript共有3种弹出对话框:Alert、Confirmation以及Prompt,Selenium 1使用的是JavaScript注入的方式来进行测试,所以无法直接处理对话框,而Selenium 2是针对各个浏览器开发的,避免了JavaScript安全模型导致的限制,因此对话框会成功弹出。
在Selenium 2中,弹出对话框统一视为Alert对象,只需调用Alert对象的方法即可。Accept()方法单击弹出对话框的确认按钮,例如:
public class Main { public static void main(String[] args) { WebDriver driver = new FirefoxDriver(); Navigation navigation = driver.navigate(); navigation.to("http://www.baidu.com"); WebElement btn = driver.findElement(By.id("getAlert")); btn.click(); driver.switchTo().alert().accept(); } }
dismiss()方法单击弹出对话框的取消按钮,例如:
public class Main { public static void main(String[] args) { WebDriver driver = new FirefoxDriver(); Navigation navigation = driver.navigate(); navigation.to("http://www.baidu.com"); WebElement btn = driver.findElement(By.id("getAlert")); btn.click(); driver.switchTo().alert().dismiss(); } }
sendKeys()方法在弹出对话框中输入文本,该方法只对Prompt弹出对话框有效,例如:
public class Main { public static void main(String[] args) { WebDriver driver = new FirefoxDriver(); Navigation navigation = driver.navigate(); navigation.to("http://www.baidu.com"); WebElement btn = driver.findElement(By.id("getAlert")); btn.click(); driver.switchTo().alert().sendKyes("Hello World"); } }
getText()方法用于获取弹出对话框的文本内容,例如:
public class Main { public static void main(String[] args) { WebDriver driver = new FirefoxDriver(); Navigation navigation = driver.navigate(); navigation.to("http://www.baidu.com"); WebElement btn = driver.findElement(By.id("getAlert")); btn.click(); string text = driver.switchTo().alert().getText(); } }
3.2 多窗口处理
在进行Web测试时,还会弹出一些子窗口,并在多个窗口之间进行切换。要在多个窗口之间进行切换,首先必须获取每个窗口的唯一标识符(句柄),通过getWindowHandles()方法可以获取所有打开窗口的标识符,并将其以集合的形式返回,例如:
public class Main { public static void main(String[] args) { WebDriver driver = new FirefoxDriver(); Navigation navigation = driver.navigate(); navigation.to("http://www.baidu.com"); String[] handles = new String[driver.getWindowHandles().size]; driver.getWindowHandles().toArray(handles); for (int i = 0; i < handles.length; i++) { System.out.println(handles[i]); } } }
新窗口弹出后,可以通过它的标识符(句柄)切换到该窗口,再对该窗口的元素进行操作,例如:
public class Main { public static void main(String[] args) { WebDriver driver = new FirefoxDriver(); Navigation navigation = driver.navigate(); navigation.to("http://www.baidu.com"); WebElement loginLink = driver.findElement(By.name("tj_login")); loginLink.click(); WebElement regLink = driver.findElement(By.className("pass-reglink")); regLink.click(); String[] handles = new String[driver.getWindowHandles().size]; driver.getWindowHandles().toArray(handles); driver.switchTo().window(handles[1]); } }
3.3 设置管理
在Selenium2中,可以通过Options对象对测试进行设置,包括Cookie、超时时间和浏览器窗口等。通过getCookies()方法可以获取当前的Cookie集合,可以对其进行读取、添加和删除,例如:
public class Main { public static void main(String[] args) { WebDriver driver = new FirefoxDriver(); Navigation navigation = driver.navigate(); navigation.to("http://www.baidu.com"); java.util.Set<Cookie> cookies = driver.manage().getCookies(); Cookie[] allCookies = new Cookie[cookies.size()]; cookies.toArray(allCookies); java.util.Calendar calendar = java.util.Calendar.getInstance(); calendar.add(java.util.Calendar.Date, +1); java.util.Date date = calendar.getTime(); Cookie newCookie = new Cookie("newcookie", "value", "baidu.com", "",date); cookies.add(newCookie); cookies.remove(allCookies[cookies.size()-1]); } }
通过window()方法可以对当前的窗口进行简单的控制,如查看窗体的坐标和大小,并最大化,例如:
public class Main { public static void main(String[] args) { WebDriver driver = new FirefoxDriver(); Navigation navigation = driver.navigate(); navigation.to("http://www.baidu.com"); Window window = driver.manage().window(); System.out.println(window.getPosition().x); System.out.println(window.getPosition().y); System.out.println(window.getSize().width); System.out.println(window.getSize().height); window.maximize(); } }
timeouts()方法会获得Timeouts对象,它包含3种方法,implicitlyWait()方法设置脚本在查找元素时的最大等待时间,setPageLoadTimeout()方法设置页面操作超时时间,setScriptTimeout()方法设置脚本异步执行的超时时间,例如:
public class Main { public static void main(String[] args) { WebDriver driver = new FirefoxDriver(); Navigation navigation = driver.navigate(); navigation.to("http://www.baidu.com"); Timeouts timeouts = driver.manage().timeouts(); timeouts.implicitlyWait(30, java.util.concurrent.TimeUnit.SECONDS); timeouts.setPageLoadTimeout(30, java.util.concurrent.TimeUnit.SECONDS); timeouts.setScriptTimeout(30, java.util.concurrent.TimeUnit.SECONDS); } }
3.4 结束测试
当测试执行完毕后,有两种方法可以结束测试,一种是使用close()方法关闭WebDriver当前所在的窗口,另一种是直接使用quit()方法关闭所有窗口,例如:
public class Main { public static void main(String[] args) { WebDriver driver = new FirefoxDriver(); Navigation navigation = driver.navigate(); navigation.to("http://www.baidu.com"); WebElement loginLink = driver.findElement(By.name("tj_login")); loginLink.click(); WebElement regLink = driver.findElement(By.className("pass-reglink")); regLink.click(); String[] handles = new String[driver.getWindowHandles().size]; driver.getWindowHandles().toArray(handles); driver.switchTo().window(handles[1]); driver.close(); driver.switchTo().window(handles[0]); driver.quit(); } }