我想为WebDriver类添加一些功能。我试过使用模式装饰器。我认为在这种情况下,在不改变它的情况下向WebDriver类添加功能是最好的。
这是我的代码:
public abstract class DriverExtends extends RemoteWebDriver {
protected Log logger = LogFactory.getLog(getClass());
protected RemoteWebDriver rwd;
protected final int SLEEP = 10;
public DriverExtends(RemoteWebDriver driver) {
rwd = driver;
}
/**
* Determines whether an element is present on the page.
* @param by The search item.
* @param log if true, logs a message in the log in the absence of the element. False otherwise.
* @return true if the element is present, false otherwise.
*/
public boolean isElementPresent(By by, boolean log) {
try{
(new WebDriverWait(rwd, SLEEP)).until(ExpectedConditions.presenceOfElementLocated(by));
return true;
} catch(NoSuchElementException e) {
if(log) {
logger.warn("L'élément est absent : "+ e.getMessage());
}
return false;
}
}
/**
* Allows click on a submenu hide default.
* @param by The link to click. Example (By.linkText ("Search"));
*/
public void loadMenu(By by) {
rwd.findElement(By.id("bouton_menu")).click();
((JavascriptExecutor)rwd).executeScript("$(\".menu2\").show()");
rwd.findElement(by).click();
}
}
FirefoxDriverExtends.class
public class FirefoxDriverExtends extends DriverExtends {
public FirefoxDriverExtends (FirefoxDriver driver) {
super(driver);
}
}
我的测试用例:
public class CreatePeople extends DefaultTestCaseWithParam<PersonLoaded> {
@Override
public boolean test(DriverExtends driver, PersonLoaded p) throws InterruptedException, TimeoutException {
System.out.println("CreatePeople.test() - " + p);
driver.loadMenu(By.linkText("Recherche"));
(new WebDriverWait(driver, SLEEP)).until(ExpectedConditions.presenceOfElementLocated(By.id("idform:nom_input"))).sendKeys(p.getPrenom());
driver.findElement(By.id("idform:datenaiss_input")).sendKeys(p.getDateNaiss());
new Select(driver.findElement(By.id("idform:paysRR"))).selectByValue("Danemark");
(new WebDriverWait(driver, SLEEP)).until(ExpectedConditions.elementToBeClickable(By.id("idform:villeRR"))).sendKeys("COPENHAGUE");
driver.findElement(By.id("idform:rechercherRes")).click();
(new WebDriverWait(driver, SLEEP)).until(ExpectedConditions.presenceOfElementLocated(By.id("idform:creerRes"))).click();
new Select((new WebDriverWait(driver, SLEEP)).until(ExpectedConditions.presenceOfElementLocated(By.id("People:selecGestio")))).selectByVisibleText("SELENIUM-UN SELENIUM");
driver.findElement(By.id("People:adresse")).sendKeys("01 rue du test");
driver.findElement(By.id("People:telT")).sendKeys("0102030405");
new Select(driver.findElement(By.id("People:posS"))).selectByVisibleText("someText");
new Select((new WebDriverWait(driver, SLEEP)).until(ExpectedConditions.presenceOfElementLocated(By.id("People:categAD")))).selectByVisibleText("someText");
new Select(driver.findElement(By.id("People:autoEmploi"))).selectByVisibleText("Armée de l'air");
new Select((new WebDriverWait(driver, SLEEP)).until(ExpectedConditions.presenceOfElementLocated(By.id("People:categP")))).selectByVisibleText("someText");
new Select(driver.findElement(By.id("People:precMili"))).selectByVisibleText("De carrière");
new Select((new WebDriverWait(driver, SLEEP)).until(ExpectedConditions.presenceOfElementLocated(By.id("People:categH")))).selectByVisibleText("someText");
driver.findElement(By.id("id=People:date_debut-service_input")).click();
driver.findElement(By.linkText("1")).click();
return true;
}
}
这就是我得到的错误:
uild info: version: '2.41.0', revision: '3192d8a6c4449dc285928ba024779344f5423c58', time: '2014-03-27 11:29:39'
System info: host: 'UCFC4DD43D730B', ip: '36.138.1.237', os.name: 'Windows 7', os.arch: 'amd64', os.version: '6.1', java.version: '1.7.0_25'
Driver info: driver.version: RemoteWebDriver
org.openqa.selenium.remote.UnreachableBrowserException: Error communicating with the remote browser. It may have died.
Build info: version: '2.41.0', revision: '3192d8a6c4449dc285928ba024779344f5423c58', time: '2014-03-27 11:29:39'
System info: host: 'UCFC4DD43D730B', ip: '36.138.1.237', os.name: 'Windows 7', os.arch: 'amd64', os.version: '6.1', java.version: '1.7.0_25'
Driver info: driver.version: RemoteWebDriver
at org.openqa.selenium.remote.RemoteWebDriver.execute(RemoteWebDriver.java:589)
-Start of the timer for "Test 4 - selenium.tests.testsuites.TestSuitePeople.testCreatePeople"
09/04/2014 15:10:00 (DbUnit.java:173) [INFO ]: Désactivation des contraintes
at org.openqa.selenium.remote.RemoteWebDriver.execute(RemoteWebDriver.java:610)
at org.openqa.selenium.remote.RemoteWebDriver.getScreenshotAs(RemoteWebDriver.java:320)
at selenium.utils.jUnit.SeleniumTestWatcher.failed(SeleniumTestWatcher.java:68)
at org.junit.rules.TestWatchman$1.evaluate(TestWatchman.java:51)
at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:28)
at org.junit.internal.runners.statements.RunAfters.evaluate(RunAfters.java:31)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:76)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:50)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:193)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:52)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:191)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:42)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:184)
at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:28)
at org.junit.internal.runners.statements.RunAfters.evaluate(RunAfters.java:31)
at org.junit.runners.ParentRunner.run(ParentRunner.java:236)
at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:50)
at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:467)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:683)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:390)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:197)
Caused by: java.lang.NullPointerException
at org.openqa.selenium.remote.RemoteWebDriver.execute(RemoteWebDriver.java:568)
... 22 more
这是我第一次使用装饰器模式。那么我错过了什么? :)
答案 0 :(得分:0)
我假设,问题在于RemoteWebDriver的初始化。您不能将firefox驱动程序注入RWD对象而是指定功能。查看this doc.
答案 1 :(得分:0)
好的,我已经找到了如何做到这一点。这是解决方案。在装饰器模式中,您必须使用装饰器对象映射装饰对象的所有方法。
首先我们可以看到RemoteWebDriver.class是所有webDriver对象的超类。因此,为了装饰RemoteWebDriver,我们必须创建实现所有RemoteWebDriver接口的类。
public abstract class DriverCustom implements WebDriver, JavascriptExecutor,
FindsById, FindsByClassName, FindsByLinkText, FindsByName,
FindsByCssSelector, FindsByTagName, FindsByXPath,
HasInputDevices, HasCapabilities, TakesScreenshot {
//Our decorated object
protected RemoteWebDriver rwd;
public DriverCustom(RemoteWebDriver driver) {
rwd = driver;
}
// custom methods to add to the decorator. Must be public.
}
接下来,我们需要使用我们的浏览器实现来实现这个装饰器。让我们来看看Firefox的例子吧。在这个类中,我们需要将所有方法映射到相应的FirefoxDriver类
public class FirefoxDriverCustom extends DriverCustom {
// Add decorated object to decorator
public FirefoxDriverCustom(FirefoxDriver driver) {
super(driver);
}
@Override
public void get(String url) {
rwd.get(url);
}
@Override
public String getCurrentUrl() {
return rwd.getCurrentUrl();
}
@Override
public String getTitle() {
return rwd.getTitle();
}
@Override
public List<WebElement> findElements(By by) {
return rwd.findElements(by);
}
@Override
public WebElement findElement(By by) {
return rwd.findElement(by);
}
@Override
public String getPageSource() {
return rwd.getPageSource();
}
@Override
public void close() {
rwd.close();
}
@Override
public void quit() {
rwd.close();
}
@Override
public Set<String> getWindowHandles() {
return rwd.getWindowHandles();
}
@Override
public String getWindowHandle() {
return rwd.getWindowHandle();
}
@Override
public TargetLocator switchTo() {
return rwd.switchTo();
}
@Override
public Navigation navigate() {
return rwd.navigate();
}
@Override
public Options manage() {
return rwd.manage();
}
@Override
public Object executeScript(String script, Object... args) {
return rwd.executeScript(script, args);
}
@Override
public Object executeAsyncScript(String script, Object... args) {
return rwd.executeAsyncScript(script, args);
}
@Override
public WebElement findElementById(String using) {
return rwd.findElementById(using);
}
@Override
public List<WebElement> findElementsById(String using) {
return rwd.findElementsById(using);
}
@Override
public WebElement findElementByClassName(String using) {
return rwd.findElementByClassName(using);
}
@Override
public List<WebElement> findElementsByClassName(String using) {
return rwd.findElementsByClassName(using);
}
@Override
public WebElement findElementByLinkText(String using) {
return rwd.findElementByLinkText(using);
}
@Override
public List<WebElement> findElementsByLinkText(String using) {
return rwd.findElementsByLinkText(using);
}
@Override
public WebElement findElementByPartialLinkText(String using) {
return rwd.findElementByPartialLinkText(using);
}
@Override
public List<WebElement> findElementsByPartialLinkText(String using) {
return rwd.findElementsByPartialLinkText(using);
}
@Override
public WebElement findElementByName(String using) {
return rwd.findElementByName(using);
}
@Override
public List<WebElement> findElementsByName(String using) {
return findElementsByName(using);
}
@Override
public WebElement findElementByCssSelector(String using) {
return rwd.findElementByCssSelector(using);
}
@Override
public List<WebElement> findElementsByCssSelector(String using) {
return rwd.findElementsByCssSelector(using);
}
@Override
public WebElement findElementByTagName(String using) {
return rwd.findElementByTagName(using);
}
@Override
public List<WebElement> findElementsByTagName(String using) {
return rwd.findElementsByTagName(using);
}
@Override
public WebElement findElementByXPath(String using) {
return rwd.findElementByXPath(using);
}
@Override
public List<WebElement> findElementsByXPath(String using) {
return rwd.findElementsByXPath(using);
}
@Override
public Keyboard getKeyboard() {
return rwd.getKeyboard();
}
@Override
public Mouse getMouse() {
return rwd.getMouse();
}
@Override
public Capabilities getCapabilities() {
return rwd.getCapabilities();
}
@Override
public <X> X getScreenshotAs(OutputType<X> target)
throws WebDriverException {
return rwd.getScreenshotAs(target);
}
// We can also add some specific firefox's methods to our decorator class.
}