Monday, October 6, 2008

Starting Selenium Server in Java


For some of our automated tests we are switching to use the open-source project Selenium-RC. You can read more about it at its web site: http://selenium-rc.openqa.org/, but essentially it runs a java server which can control an internet browser, and then your testing code sends commands to this server. One key part of this setup is that you need the server running while your testing code is executing. For automated testing machines it would be no big deal to make the Selenium server a service; however developers probably don’t want it running all the time—in fact they do not want to think about it!



Thus our solution was to have our testing code launch the server. I’ve seen a number of posts on various forums asking how to start the selenium server form Java, but none of them had concrete answers. Thus I will reproduce our implementation for you to use and modify as you please:




Process p = null;

try {

    String[] cmd = {"java","-jar","C:\\<path to selenium>\\server\\selenium-server.jar" };

    p = Runtime.getRuntime().exec(cmd);

} catch (IOException e) {

    System.out.println("IOException caught: "+e.getMessage());

    e.printStackTrace();

}


System.out.println("Waiting for server...");

int sec = 0;

int timeout = 20;

boolean serverReady = false;

try {

    BufferedReader input = new BufferedReader(new InputStreamReader(p.getInputStream()));

    while (sec < timeout && !serverReady) {

        while (input.ready()) {

            String line = input.readLine();

            System.out.println("From selenium: "+line);

            if (line.contains("Started HttpContext[/,/]")) {

                serverReady = true;

            }

    }

        Thread.sleep(1000);

         ++sec;

    }

    input.close();

} catch (Exception e) {

    System.out.println("Exception caught: "+e.getMessage());

}



if (!serverReady) {

    throw new RuntimeException("Selenium server not ready");

}



System.out.println("Done waiting");



Some notes on the above code:

  • I left in some handy print statements; however these are of course completely optional.

  • For non-automated testing machines, be sure to have your outer most try-catch block of your testing code kill the server or it may be left running even when the testing code finishes.

  • For code on automated testing machines, you may want to check to see if the server is running and start it only if it is not. This way you don’t waste time waiting for the server to be ready if another test already brought it up.


  • 5 comments:

    Unknown said...

    thanks for the code. that saved me at least an hour of mucking about :)

    Unknown said...

    I am certainly not a Selenium expert by any stretch of the imagination. Found this blog via a post on AdvancedQTP. However, I have messed around with Selenium and to start a server from within your Java code, you can just add the selenium-server.jar to your project and call:

    SeleniumServer selServer = new SeleniumServer(); selServer.start();

    This has worked just fine for me. Then you can handle exceptions and other config right in Java code. No need for the command line.

    Aaron Silverman said...

    Great find Christian! If you want to include the server jar in your project (which would help organize things too!) this is a much simpler way to invoke the server. Thanks for sharing!

    One advantage of starting the server as a command line call is that the selenium server is left running. Thus if test execution hits an error you can pick up where you left off (helpful for debugging) as your new selenium calls still go to the same server. Does starting the server this way allow it to continue even when the program execution terminates?

    Unknown said...

    Yes, as far as I know, you can leave it running. I can't really remember as I haven't messed with Selenium in quite a while, but I seem to remember an error happening somewhere in a test (before calling selServer.Stop()) and me having to kill the process via the command line. This was before I figured out that you can just extend the SeleneseTestCase class and put the selServer.Stop() call in the tearDown() method (if you want it to be a JUnit-controlled test) or in a @AfterClass annotated method (if you want it to be a TestNG-controlled test).

    If you similarly put the selServer.Start() command in setUp() (JUnit) or @BeforeClass (TestNG) method it gives you a self-contained test that starts and stops it's own Selenium Server and Remote Control. I used both the JUnit overrides and the TestNG annotations so that I could run the test case with either.

    Since the @BeforeClass setUp() and @AfterClass tearDown() do the starting and stopping, you never have the problem with the the server running past its self-contained test case, even if there is an error since that always runs for cleanup after a JUnit/TestNG test. This made it more like QTP for me. I could just run test cases in a self-contained manner and then worry about how to group them later. Not that I really did a full automation project with Selenium anyway, I was just investigating it as an alternative to QTP.

    Unknown said...

    I should also add that I don't remember there being any ridiculous amount of start or stop times for the Server and RC, but like I said, it's been a while. I certainly don't remember it taking any amount of time that was any more irritating than QTP's script start-up time. I'm pretty sure it was slower, but not significantly so.