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 …
[...] 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 |