Selenium由于其适用多种语言(本文使用的语言为java),在自动化测试领域中的使用用越来越多。使用Selenium的方式有很多,能使用的工具也很多。PageObject模式的使用提高了测试代码的可读性与可维护性,同时一定程度减少了测试代码量,降低了测试用例与测试功能间的耦合程度。
目前遇到的问题:
(1)Selenium自动化测试大部分的操作都由WebDriver完成,比如在进行一次点击操作时,首先要获取Dom元素(dom元素的获取方法有很多,详见API即可),然后再调用点击的方法,每一步都要进行获取再执行的操作多有冗余。
(2)在编写测试用例时,需要初始化WebDriver,对于WebDriver的初始化在每一个页面的测试case类里都要编写一次,这里也存在冗余。
(3)如何控制两步操作间的执行时间。
对于问题(1)代码冗余的问题,笔者将WebDriver中的方法重新包装了一遍。
定义接口WebDriverWrapper
package com.test.sahagin.wrapper;
import org.openqa.selenium.WebElement;
public interface WebDriverWrapper {
/**
* 根据标签ID获取 标签元素
* @param id
* @return
*/
WebElement getElementById(String id);
/**
* 根据标签name获取 标签元素
* @param name
* @return
*/
WebElement getElementByName(String name);
/**
* 根据标签className获取 标签元素
* @param className
* @return
*/
WebElement getElementByClassName(String className);
/**
* 根据标签Css 选择器获取 标签元素
* @param selector
* @return
*/
WebElement getElementByCssSelector(String selector);
/**
* 根据标签标签名称获取 标签元素
* @param tagName
* @return
*/
WebElement getElementByTagName(String tagName);
//******************点击操作********************//
void clickByJs(String id);
void clickById(String id);
void clickByName(String name);
//*****************情空操作********************//
void clearById(String id);
//*****************赋值操作*******************//
void sendKeysById(String id, String content);
//*****************执行js操作*****************//
void executeJsById(String id, String js);
void executeJs(String js);
/**
* 选择复选框进行赋值
* @param formId
* @param tagName
* @param value
*/
void selectCheckBox(String tagName, String value[]);
/**
* 通过下拉框option的text内容选择下拉框选项
* @param selectId 下拉框ID
* @param text 下拉框选项内容
*/
void selectDropDownListByText(String selectId, String text);
/**
* 通过下拉框option的value内容选择下拉框选项
* @param selectId 下拉框ID
* @param value 下拉框选项值
*/
void selectDropDownListByValue(String selectId, String value);
/**
* 通过下拉框option的索引内容选择下拉框选项
* @param selectId 下拉框ID
* @param value 下拉框选项值
*/
void selectDropDownListByIndex(String selectId, int index);
}
package com.test.sahagin.wrapper;
import java.util.List;
import org.openqa.selenium.By;
import org.openqa.selenium.JavascriptExecutor;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.support.ui.Select;
public final class WebDriverWrapperImpl implements WebDriverWrapper{
private WebDriver webDriver;
public WebDriverWrapperImpl(WebDriver webDriver) {
super();
this.webDriver = webDriver;
}
/**
* 根据标签ID获取 标签元素
* @param id
* @return
*/
public WebElement getElementById(String id) {
return webDriver.findElement(By.id(id));
}
/**
* 根据标签name获取 标签元素
* @param name
* @return
*/
public WebElement getElementByName(String name) {
return webDriver.findElement(By.name(name));
}
/**
* 根据标签className获取 标签元素
* @param className
* @return
*/
public WebElement getElementByClassName(String className) {
return webDriver.findElement(By.className(className));
}
/**
* 根据标签Css 选择器获取 标签元素
* @param selector
* @return
*/
public WebElement getElementByCssSelector(String selector) {
return webDriver.findElement(By.cssSelector(selector));
}
/**
* 根据标签标签名称获取 标签元素
* @param tagName
* @return
*/
public WebElement getElementByTagName(String tagName) {
return webDriver.findElement(By.tagName(tagName));
}
public List<WebElement> getElementByPath(String path) {
return webDriver.findElements(By.xpath(path));
}
//******************点击操作********************//
public void clickByJs(String id) {
executeJsById(id,"arguments[0].click()");
}
public void clickById(String id) {
this.getElementById(id).click();
}
public void clickByName(String name) {
this.getElementByName(name).click();
}
//*****************情空操作********************//
public void clearById(String id) {
this.getElementById(id).clear();
}
//*****************赋值操作*******************//
public void sendKeysById(String id, String content) {
this.clearById(id);
this.getElementById(id).sendKeys(content);;
}
//*****************执行js操作*****************//
public void executeJsById(String id, String js) {
WebElement ele = this.getElementById(id);
((JavascriptExecutor)webDriver).executeScript(js, ele);
}
@Override
public void executeJs(String js) {
((JavascriptExecutor)webDriver).executeAsyncScript(js);
}
@Override
public void selectCheckBox(String tagName, String[] value) {
// List<WebElement> eles = this.getElementByPath("//*[@id='" + formId + "']/**/input[@name='"+ tagName +"']");
List<WebElement> eles = webDriver.findElements(By.name(tagName));
if (eles != null) {
for (WebElement ele : eles) {
for (int i = 0; i < value.length; i ++) {
WebElement ch = ele.findElement(By.xpath("/following-sibling::span[2]"));
if (ch != null && ch.getText().equals(value[i]))
ele.click();
}
}
}
}
@Override
public void selectDropDownListByText(String selectId, String text) {
Select select = new Select(getElementById(selectId));
select.selectByVisibleText(text);
}
@Override
public void selectDropDownListByValue(String selectId, String value) {
Select select = new Select(getElementById(selectId));
select.selectByValue(value);
}
@Override
public void selectDropDownListByIndex(String selectId, int index) {
// TODO Auto-generated method stub
Select select = new Select(getElementById(selectId));
select.selectByIndex(index);
}
}
这样在执行页面操作时,调用里面的方法就可以了。并且使用PageObject模式 之前注入的是WebDriver,现在需要注入WebDriverWrapper。再新建一个PageObject类时,可以直接继承BaseTestPage
package com.test.pages;
import org.sahagin.runlib.external.TestDoc;
import com.fujitsu.test.sahagin.wrapper.WebDriverWrapper;
public class BaseTestPage {
protected WebDriverWrapper wd;
public BaseTestPage() {
super();
}
public BaseTestPage(WebDriverWrapper wd) {
super();
this.wd = wd;
}
//在这里可以添加页面共有的操作。
@TestDoc("「管理メニュー」を押下する")
public void clickManageMenu() {
wd.clickByJs("managementMenu");
}
@TestDoc("「利用者一覧」を押下する")
public void clickUserList() {
wd.clickByJs("userList");
}
@TestDoc("「属性一覧」を押下する")
public void clickAttributeList() {
wd.clickByJs("attributeList");
}
@TestDoc("「共通公開範囲一覧」を押下する")
public void clickPublishList() {
wd.clickByJs("publishList");
}
@TestDoc("「案件書式一覧」を押下する")
public void clickItemFormatList() {
wd.clickByJs("itemFormatList");
}
@TestDoc("「案件ロック一覧」を押下する")
public void clickItemLockList() {
wd.clickByJs("itemLockList");
}
}
对于问题(2)
首先写一个工具类用于初始化WebDriver。
package com.test.sahagin.util;
import org.openqa.selenium.Platform;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.ie.InternetExplorerDriver;
import org.openqa.selenium.remote.DesiredCapabilities;
public class WebDriverUtil {
private static WebDriverUtil webDriverUtil = new WebDriverUtil();
private WebDriverUtil() {}
public static WebDriverUtil getInstance() {
return webDriverUtil;
}
public WebDriver initWebDriver() {
DesiredCapabilities capabilities = configDesiredCapabilities();
return new InternetExplorerDriver(capabilities);
}
private DesiredCapabilities configDesiredCapabilities() {
DesiredCapabilities capabilities = DesiredCapabilities.internetExplorer();
capabilities.setCapability(InternetExplorerDriver.INTRODUCE_FLAKINESS_BY_IGNORING_SECURITY_DOMAINS,true);
capabilities.setPlatform(Platform.WINDOWS);
capabilities.setCapability("silent", true);
capabilities.setCapability("ignoreZoomSetting", true);
return capabilities;
}
}
然后写一个BaseTestPage
package com.test.features;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy;
import java.util.concurrent.TimeUnit;
import org.openqa.selenium.WebDriver;
import org.sahagin.runlib.external.adapter.webdriver.WebDriverAdapter;
import com.fujitsu.test.pages.LoginPage;
import com.fujitsu.test.pages.PageURL;
import com.fujitsu.test.sahagin.util.DynamicProxy;
import com.fujitsu.test.sahagin.util.WebDriverUtil;
import com.fujitsu.test.sahagin.wrapper.WebDriverWrapper;
import com.fujitsu.test.sahagin.wrapper.WebDriverWrapperImpl;
public class BaseTestPage {
protected WebDriverWrapper webDriverWrapper;
protected WebDriver webDriver;
protected String url;
public void init() {
webDriver = WebDriverUtil.getInstance().initWebDriver();
webDriver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS);//搜索元素时超时时间
webDriver.manage().timeouts().setScriptTimeout(10, TimeUnit.SECONDS);//执行js脚本超时时间
WebDriverWrapper realWebDriverWrapper = new WebDriverWrapperImpl(webDriver);
InvocationHandler handler = new DynamicProxy(realWebDriverWrapper);
webDriverWrapper = (WebDriverWrapper) Proxy.newProxyInstance(handler.getClass().getClassLoader(),
realWebDriverWrapper.getClass().getInterfaces(), handler);//这里使用代理,作用于下文解释
WebDriverAdapter.setAdapter(webDriver);
}
//每个功能都要登录才能操作,免登陆的用法还没有实施。Cookie的用户不起作用
public void login() {
webDriver.get(PageURL.LOGINPAGEURL);//将所有的URL 放在PageUrl类中进行管理。
LoginPage loginPage = new LoginPage(webDriverWrapper);
loginPage.setUsername("ksl");
loginPage.setPassword("/ksl");
loginPage.send();
}
public void destory() {
webDriver.quit();
}
}
接下来每个页面测试继承BaseTestPage即可:
package com.fujitsu.test.features;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import com.fujitsu.test.pages.LoginPage;
import com.fujitsu.test.pages.PageURL;
public class TestLoginPage extends BaseTestPage{
@Before
public void initWd() {
super.init();
}
@Test
public void testLoginCorrect() {
webDriver.get(PageURL.LOGINPAGEURL);
LoginPage loginPage = new LoginPage(webDriverWrapper);
loginPage.setUsername("ksl");
loginPage.setPassword("/ksl");
loginPage.send();
}
@Test
public void testLoginInCorrect() {
webDriver.get(url);
LoginPage loginPage = new LoginPage(webDriverWrapper);
loginPage.setUsername("ksl");
loginPage.setPassword("/ksl");
loginPage.send();
}
@After
public void destoryWd() {
webDriver.quit();
}
}
package com.test.sahagin.util;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import com.fujitsu.test.pages.PageURL;
public class DynamicProxy implements InvocationHandler {
private Object subject;
public DynamicProxy(Object subject) {
super();
this.subject = subject;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Thread.sleep(PageURL.SLEEPTIME);//每个方法执行前都会调用sleep方法。
method.invoke(subject, args);
return null;
}
}
pom文件:
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.fnst</groupId>
<artifactId>test</artifactId>
<version>0.0.1-SNAPSHOT</version>
<properties>
<sahagin.version>0.9.2</sahagin.version>
</properties>
<dependencies>
<dependency>
<groupId>org.seleniumhq.selenium</groupId>
<artifactId>selenium-java</artifactId>
<version>2.53.1</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.apache.commons/commons-exec -->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-exec</artifactId>
<version>1.3</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.slf4j/slf4j-nop -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-nop</artifactId>
<version>1.7.23</version>
</dependency>
<!-- https://mvnrepository.com/artifact/commons-io/commons-io -->
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.4</version>
</dependency>
<dependency>
<groupId>com.opera</groupId>
<artifactId>operadriver</artifactId>
</dependency>
<dependency>
<groupId>org.sahagin</groupId>
<artifactId>sahagin</artifactId>
<version>${sahagin.version}</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>net.lightbody.bmp</groupId>
<artifactId>browsermob-core</artifactId>
<version>2.1.4</version>
<scope>test</scope>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>com.opera</groupId>
<artifactId>operadriver</artifactId>
<version>0.16</version>
<exclusions>
<exclusion>
<groupId>org.seleniumhq.selenium</groupId>
<artifactId>selenium-remote-driver</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies>
</dependencyManagement>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>2.5.1</version>
<configuration>
<source>1.7</source>
<target>1.7</target>
<encoding>UTF-8</encoding>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-resources-plugin</artifactId>
<version>2.4</version>
<configuration>
<encoding>UTF-8</encoding>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.18 </version>
<configuration>
<forkCount>3</forkCount>
<reuseForks>true</reuseForks>
<argLine>
-javaagent:${settings.localRepository}/org/sahagin/sahagin/${sahagin.version}/sahagin-${sahagin.version}.jar
</argLine>
<useSystemClassLoader>true</useSystemClassLoader>
</configuration>
</plugin>
</plugins>
</build>
</project>