Sunday, June 29, 2008

Running Selenium inside JUnit

Selenium is a framework which makes testing a web application possible, in an automated fashion. It helps us record test scripts in various formats and run it on the web application.
Selenium brings you three components. One of those, Selenium-ide is available as a firefox extension which can record your actions on a web page and then re-run it. Another component called selenium-core helps you copy the test-scripts over to the server and run it from there. This is helpful when you need more control over the way tests are run. Third one, which we are particularly interested in, is the selenium-remote. Selenium-remote has a server and client architecture.

JUnit is a unit testing framework (okay, I know you know that!). It is possible to
combine jUnit and Selelnium to write powerful client side test scripts. One advantage is that selenium testscripts can be made part of your build process.


Now, lets get into action. Download the selenium-remote.

First step would be to run the selenium-server. The server acts as a intercepting server
for the client (the client is mostly the browser).

$java -jar selenium-server.jar
19:18:09.156 INFO - Java: Sun Microsystems Inc. 10.0-b22
19:18:09.156 INFO - OS: Windows XP 5.1 x86
19:18:09.156 INFO - v0.9.2 [2006], with Core v0.8.3 [1879]
19:18:09.500 INFO - Version Jetty/5.1.x
19:18:09.500 INFO - Started HttpContext[/selenium-server/driver,/selenium-server
/driver]
19:18:09.500 INFO - Started HttpContext[/selenium-server,/selenium-server]
19:18:09.500 INFO - Started HttpContext[/,/]
19:18:09.828 INFO - Started SocketListener on 0.0.0.0:4444
19:18:09.828 INFO - Started org.mortbay.jetty.Server@6d084b


Server is up and running on port 4444 (of course you can change the port, take a look at the command line options)

You are now ready for the jUnit test case. A simple one :

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

import junit.framework.TestCase;


public class DummyTest extends TestCase {

Selenium selenium = null; // selenium object represents the browser

public void setUp() {
// Open the browser, connect to selenium server on localhost:4444. the basedomain is www.inapp.com
// *firefox is the browser command for Firefox, *iexplore for IE.
selenium = new DefaultSelenium("localhost", 4444, "*iexplore", "http://www.inapp.com" );
}

public void testDummyFunction() throws Exception {
selenium.open("http://www.inapp.com"); // open the url in browser
assertTrue(selenium.getTitle().startsWith("InApp")); // the test!
selenium.close();
}
}


Note that you have to specify a base-domain while instantiating DefaultBrowser. A url from another domain cannot be opened from the browser for security reasons.
Dont forget to include selenium-java-client.jar in your classpath.


Lets look at another example :

import com.thoughtworks.selenium.SeleneseTestCase;

public class DummyTest extends SeleneseTestCase { //Notice that we extend 'SeleneseTestCase' instead of 'TestCase'

public void testDummyFunction() throws Exception {
setUp("http://www.inapp.com", "*firefox"); // initialize the DefaultBrowser
selenium.open("http://www.inapp.com"); // open the url in browser
assertTrue(selenium.getTitle().startsWith("InApp")); // the test!
selenium.close();
}
}


We make use of SeleneseTestCase provided by selenium remote. It makes the code concise.

The DefaultBrowser class have lot of methods which we can use in order to validate the content in the browser and fire events. You event have a 'captureScreenshot' method to get a screenshot of your browser. So next time you have a test fail, get the screenshot mailed to you :)

6 comments:

  1. hi Nishan,

    Great post. I am new to both Junit and selenium. I want to generate a basic report from these test cases result. How would i go about doing that. Thanks in advance.

    ReplyDelete
  2. I tried running above 1st Code in JUNit but It is not working for me.. I am getting below exception on eclipse.

    junit.framework.AssertionFailedError: TestCase.fName cannot be null
    at junit.framework.Assert.fail(Assert.java:47)
    at junit.framework.Assert.assertTrue(Assert.java:20)
    at junit.framework.Assert.assertNotNull(Assert.java:214)
    at junit.framework.TestCase.runTest(TestCase.java:152)
    at junit.framework.TestCase.runBare(TestCase.java:134)
    at junit.framework.TestResult$1.protect(TestResult.java:110)
    at junit.framework.TestResult.runProtected(TestResult.java:128)
    at junit.framework.TestResult.run(TestResult.java:113)
    at junit.framework.TestCase.run(TestCase.java:124)
    at junit.framework.TestSuite.runTest(TestSuite.java:232)
    at junit.framework.TestSuite.run(TestSuite.java:227)
    at org.junit.internal.runners.JUnit38ClassRunner.run(JUnit38ClassRunner.java:91)
    at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:45)
    at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:460)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:673)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:386)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:196)



    Can you please help me on this??

    Thanks!
    Tiger

    ReplyDelete
  3. yeah I got the Solution..! :)

    We need to provide testcase name while adding testcase in a test suite.

    thanks!

    ReplyDelete
  4. Hi nishan,

    What is the diff between extending Testcase and extending seleneseTestcase?

    Thanks in advance,
    Sanjeev

    ReplyDelete
  5. @Sanjeev,

    SeleneseTestcase is a subclass of TestCase. It provides many utility functions so that we can save writing code. For eg: see the setUp(url, browser) method. It also initializes a default selenium object for our use.

    ReplyDelete
  6. In your first example, you need to call the the selenium.start() function after creating the DefaultSelenium object, before any open() calls.

    ReplyDelete

Bookmark

AddThis Social Bookmark Button