After some tests with HtmlUnit I decided to give Selenium another try. Selenium has a nice interactive mode with the SeleniumIDE, but for our use, we need JUnit-based tests. JUnit and Selenium means that one has to use Selenium RC (RC= Remote Control).
With Selenium RC you start a Jetty-server that controls the browser that then accesses your web-application. With this cofiguration it is possible to use 3 different computers (1 to run the JUnit tests, 1 to host the SeleniumRC server and the browser and 1 to host the web-application), but the API’s for the Selenium-RC server expose the underlying Jetty-server. With this a minimal installation could host the web-applicaiton within the Selenium-RC server. The tutorial usually show how to start the Selenium-RC server from the command-line or from the Ant-scripts.
I prefer to start and stop the Selenium-RC server from Java-code. In order to maintain the maximum flexibility I created a simple class that controls the Selenium-RC server. This allows to start the server before the whole test-suite or (the other extreme) for each single test-method.
import org.openqa.selenium.server.SeleniumServer;
public class SeleniumServerControl {
private static final SeleniumServerControl instance = new SeleniumServerControl();
public static SeleniumServerControl getInstance() {
return instance;
}
private SeleniumServer server = null;
protected SeleniumServerControl() {
}
public void startSeleniumServer() {
if (server == null) {
try {
server = new SeleniumServer(SeleniumServer.DEFAULT_PORT);
System.out.println(" selenium server " + server.toString());
} catch (Exception e) {
System.err.println("Could not create Selenium Server because of: "
+ e.getMessage());
e.printStackTrace();
}
}
try {
server.start();
} catch (Exception e) {
System.err.println("Could not start Selenium Server because of: "
+ e.getMessage());
e.printStackTrace();
}
}
public void stopSeleniumServer() {
if (server != null) {
try {
server.stop();
server = null;
} catch (Exception e) {
System.err.println("Could not stop Selenium Server because of: "
+ e.getMessage());
e.printStackTrace();
}
}
}
}
In its current form it starts the Selenium-RC server with its default-values and has only reduced error-handling. But for the moment it works.
In our setup we want to start the Selenium-RC server once for the complete test-suite. The JUnit-version is 4 which is more fexible using annotated testcasesand the setupBeforeClass-method, but seemingly has lost the test-suite that was available older JUnit versions. After some hours spent cruising the net I found this solution:
Basically it uses the old JUnit-testsuite feature to run the new testcases. The actual test-suite looks like this:
import org.junit.runner.RunWith;
import org.junit.runners.Suite;
@RunWith(Suite.class)
@Suite.SuiteClasses({
TestHomePage.class
, TestTabbedPane.class
})
public class TestSuite extends SeleniumTestSuite {
// gotta get used to empty class-bodies...
}
And the referenced parent-class:
import org.junit.AfterClass;
import org.junit.BeforeClass;
import com.csg.jsftest.selenium.base.SeleniumServerControl;
public abstract class SeleniumTestSuite {
@BeforeClass
public static void setUpBeforeClass() throws Exception {
SeleniumServerControl.getInstance().startSeleniumServer();
}
@AfterClass
public static void tearDownAfterClass() throws Exception {
SeleniumServerControl.getInstance().stopSeleniumServer();
}
}
I still have to research whether it is a Java- or a JUnit-feature that executes the parent-classes static methods when instantiating the actual test-suite. Anyway thanks to this behaviour the actual test-suite setup can be done in the common parent-class. It’s also nice that the @BeforeClass and @AfterClass annotations are executed even though no actual @Test annotation is present.
Now its time to write the testcases … and maybe some helper-methods in a parent-class?
… to be continued …