简体   繁体   中英

how to decorate the selenium WebDriver class?

I want to add some functionality to the WebDriver class. I've tried to use the pattern decorator. I think it's the best in this situation for add functionalities to WebDriver class without change it.

This my code :

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

}

My test case :

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

And this the error i get :

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

It's the first time i use the decorator pattern. So what i've missed? :)

i assume, the issue is with initialization of RemoteWebDriver. You cannot inject the firefox driver to RWD object rather specify the capabilities. Check this doc.

Ok, i've found how to do this. This is the solution. In decorator pattern you must map all method of decorated object with the decorator object.

First we can see that RemoteWebDriver.class is the super class of all webDriver objects. So to decorate RemoteWebDriver we must create class that implement all of RemoteWebDriver's interfaces.

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.

}

Next we need to implements this decorator with our browser implementation. Let's go with firefox example. In this class we need to map all methods to the corresponding FirefoxDriver class

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.

}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM