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>