Musings about this and that

September 3, 2007

More Unit-testing with Selenium

Filed under: JSF, Selenium, Unit Testing — ajesse @ 8:20 pm

Some of my first Selenium unit-tests showed some strange behaviour: Every now and then a test would fail, even though a minute ago it worked and neither the test-code nor the webapp has been changed, I almost got the impression that it would be impossible to use Selenium for automated unit-testing of our framework: oo many releases would not be flagged as stable, because of erratically failed unit-tests.

Don’t know why, but at some point it dawned that maybe there was … a timing problem. Maybe some assertions were called before the result was delivered to the browser… and in the Selenium API I found methods like selenium.waitForPageToLoad(PAGE_LOAD_TIMEOUT) … isn’t that inspiring? Some tests and yes that was the solution. But use that method-call after each action? NO WAY

So time to write my SeleniumTestCase to be used as the base class and full of goodies (convenience methods):

import static org.junit.Assert.assertEquals;

import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
import org.openqa.selenium.server.SeleniumServer;

import com.thoughtworks.selenium.DefaultSelenium;
import com.thoughtworks.selenium.Selenium;
import com.thoughtworks.selenium.SeleniumException;

public abstract class SeleniumTestCase {

  public static final String PAGE_LOAD_TIMEOUT = "10000";
  public static final String BASE_URL = "http://localhost:8080/myWebApp/";

  protected static Selenium seleniumStatic;
  protected Selenium selenium = null;

  public SeleniumTestCase() {
    this.selenium = seleniumStatic;
  }

  @BeforeClass
  public static void setUpBeforeClass() throws Exception {
    seleniumStatic = new DefaultSelenium("localhost", SeleniumServer.getDefaultPort(), "*firefox", BASE_URL);
    seleniumStatic.start();
  }

  @AfterClass
  public static void tearDownAfterClass() throws Exception {
    seleniumStatic.stop();
  }

  @Before
  public void setUp() throws Exception {
  }

  public boolean isAttributeMissing(String xPath){
    boolean result = true;
    try {
      selenium.getAttribute(xPath);
      result = false;
    } catch (SeleniumException e) {
      if (e.getMessage().contains("ERROR: Could not find element attribute: " + xPath)) {
        result = true;
      } else {
        throw(e);
      }
    }
    return result;
  }

  public boolean isElementMissing(String xPath){
    boolean result = true;
    try {
      selenium.getElementIndex(xPath);
      result = false;
    } catch (SeleniumException e) {
      if (e.getMessage().contains("ERROR: Element " + xPath + " not found")) {
        result = true;
      } else {
        throw(e);
      }
    }
    return result;
  }

  public Object getAttribute(String xPath){
    Object result = null;
    try {
      result = selenium.getAttribute(xPath);
    } catch (SeleniumException e) {
      if (e.getMessage().contains("ERROR: Could not find element attribute: " + xPath)) {
        result = null;
      } else {
        throw(e);
      }
    }
    return result;
  }

  public boolean submitAndWait(String formLocator) {
    boolean result = false;
    try {
      selenium.submit(formLocator);
      selenium.waitForPageToLoad(PAGE_LOAD_TIMEOUT);
      result = true;
    } catch (Throwable t) {
      result = false;
      System.err.println("--- received an exception: " + t);
    }

    return result;
  }

  public boolean clickAndWait(String elementLocator) {
    boolean result = false;
    try {
      selenium.click(elementLocator);
      selenium.waitForPageToLoad(PAGE_LOAD_TIMEOUT);
      result = true;
    } catch (Throwable t) {
      result = false;
      System.err.println("--- received an exception: " + t);
    }

    return result;
  }

  public boolean openAndWait(String url) {
    boolean result = false;
    try {
      selenium.open(url);
      selenium.waitForPageToLoad(PAGE_LOAD_TIMEOUT);
      result = true;
    } catch (Throwable t) {
      result = false;
      System.err.println("--- received an exception: " + t);
    }

    return result;
  }
}

With that base class, the tests can look like this:

selenium.type("id=containerForm:hideUser", "hide");
submitAndWait("id=containerForm");

… to be continued …

1 Comment »

  1. [...] UnitTest — ajesse @ 6:47 pm Since the original post introducing SeleniumControl and SeleniumTestCase these two classes learned some more [...]

    Pingback by New tricks for SeleniumControl and SeleniumTestCase « Musings about this and that — November 12, 2007 @ 7:00 pm |


RSS feed for comments on this post. TrackBack URI

Leave a comment

You must be logged in to post a comment.

Blog at WordPress.com.