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();
  }
}