Tuesday, January 03, 2012

Running Selenium tests in parallel

This post explains how to set up a concurrent execution environment and considerably reduce your testing times.
We can run multiple testcases across different browsers at a time using TestNG's configuration file.

          Below is the class that defines four methods, 'startSeleniumServer()' method is for start the server (if not started in the current port) before suite i.e before test classes in suite started runnig and the method 'stopSeleniumServer()' is for stop the server after the suite i.e after runnig  the test classes in suite (you can make these to execute class level as well, if necessary).The method 'startSelenium()' accepts two parameters i.e 'port' and 'browser' from the TestNG's configuration file.This method initiates the selenium, starting the browser before each test run and the method 'stopSelenium()' ends the test session, killing the browser.
//MasterTest.java
  1. package master;
  2. import org.openqa.selenium.server.RemoteControlConfiguration;
  3. import org.openqa.selenium.server.SeleniumServer;
  4. import org.testng.annotations.AfterClass;
  5. import org.testng.annotations.AfterSuite;
  6. import org.testng.annotations.BeforeClass;
  7. import org.testng.annotations.BeforeSuite;
  8. import org.testng.annotations.Parameters;
  9. import com.thoughtworks.selenium.DefaultSelenium;
  10. import com.thoughtworks.selenium.Selenium;
  11. public class MasterTest {
  12.    
  13.     protected RemoteControlConfiguration rc ;
  14.     protected SeleniumServer seleniumServer ;
  15.     public Selenium selenium;
  16.    
  17.     @BeforeSuite
  18.     public void startSeleniumServer()throws Exception{
  19.         rc = new RemoteControlConfiguration();  
  20.         seleniumServer = new SeleniumServer(rc);
  21.         if(!seleniumServer.getServer().isStarted()){  
  22.             seleniumServer.start();        
  23.         }
  24.     }
  25.    
  26.     @Parameters({"port","browser"})
  27.     @BeforeClass
  28.     public void startSelenium(int port,String browser) {
  29.         System.err.println("INFO: The test '"+this.getClass().getName()+"' is running on browser '"+browser+"'");
  30.         selenium = new DefaultSelenium("localhost", port, browser, "http://www.google.co.in");
  31.         selenium.start();
  32.         selenium.windowMaximize();
  33.         selenium.windowFocus();
  34.     }
  35.    
  36.     @AfterClass
  37.     public void stopSelenium() throws Exception {
  38.         selenium.stop();
  39.      }
  40.    
  41.     @AfterSuite
  42.     public void stopSeleniumServer()throws Exception {
  43.         seleniumServer.stop();
  44.     }      
  45. }
              Below is the class that runs in firefox browser.This class extends from 'MasterTest' so that before 'FirefoxTest' the selenium server will start, if not started and after this test run the selenium server will stop.
    //FirefoxTest.java
    1. package master;
    2. import org.testng.annotations.Test;
    3. public class FirefoxTest extends MasterTest {      
    4.    
    5.     @Test
    6.     public void firefoxTest() throws Exception {
    7.         selenium.setSpeed("1000");
    8.         selenium.open("/");
    9.         selenium.type("id=lst-ib""selenium");
    10.         selenium.click("name=btnG");
    11.         selenium.click("link=Selenium - Web Browser Automation");
    12.         selenium.waitForPageToLoad("30000");
    13.     }
    14. }
              Below is the class that runs in google chrome browser.This class also extends from 'MasterTest' so that before 'ChromeTest' the selenium server will start, if not started and after this test run the selenium server will stop.
    // ChromeTest .java
    1. package master;
    2. import org.testng.annotations.Test;
    3. public class ChromeTest extends MasterTest {       
    4.    
    5.     @Test
    6.     public void chromeTest() throws Exception {
    7.         selenium.setSpeed("1000");
    8.         selenium.open("/");
    9.         selenium.waitForPageToLoad("30000");
    10.         selenium.type("id=lst-ib""selenium rc");
    11.         selenium.click("name=btnG");
    12.         selenium.click("css=em");
    13.         selenium.waitForPageToLoad("30000");
    14.     }
    15. }
              Below is the class that runs in Internet Explorer browser.This class also extends from 'MasterTest' so that before 'IETest' the selenium server will start, if not started and after this test run the selenium server will stop.
    // IETest .java
    1. package master;
    2. import org.testng.annotations.Test;
    3. public class IETest extends MasterTest {
    4.    
    5.     @Test
    6.     public void ieTest() throws Exception {
    7.         selenium.setSpeed("1000");
    8.         selenium.open("/");
    9.         selenium.type("id=lst-ib""selenium");
    10.         selenium.click("name=btnG");
    11.         selenium.click("link=Selenium - Web Browser Automation");
    12.         selenium.waitForPageToLoad("30000");
    13.     }  
    14. }
              Finally, here is the TestNG's configuration file that runs all the tests giving 'port' and 'browser' as input parameters to the 'MasterTest' in each and every test run.
              The attribute 'thread-count' allows to specify how many threads should be allocated for the execution. Here i have used thread-count="3" i.e  3 threads are allocated for the tests execution.Another attribute here i have used  is 'parallel'.It takes 3 values i.e 
    parallel="methods":
        TestNG will run all the test methods in separate threads.
    parallel="tests": 
        TestNG will run all the methods in the same <test> tag in the same thread, but each <test> tag will be in a separate thread.
    parallel="classes": 
        TestNG will run all the methods in the same class in the same thread, but each class will be run in a separate thread.
    //testng.xml
    1. <suite name="Parallel Run Suite" parallel="classes"  thread-count="3">
    2.     <test name="Test-1">
    3.         <parameter name="port" value="4444" />
    4.         <parameter name="browser" value="*firefox" />
    5.         <classes>
    6.             <class name="master.FirefoxTest" />
    7.         </classes>
    8.     </test>
    9.    
    10.     <test name="Test-2">
    11.         <parameter name="port" value="4444" />
    12.         <parameter name="browser" value="*googlechrome" />
    13.         <classes>
    14.             <class name="master.ChromeTest" />
    15.         </classes>
    16.     </test>
    17.    
    18.     <test name="Test-3">
    19.         <parameter name="port" value="4444" />
    20.         <parameter name="browser" value="*iexplore" />
    21.         <classes>
    22.             <class name="master.IETest" />
    23.         </classes>
    24.     </test>
    25.    
    26. </suite>
              So, when you will run the above TestNG's configuration file, firstly, it will run 'FirefoxTest' in firefox browser,secondly, it will run 'ChromeTest' in chrome browser and thirdly, it will run 'IETest' in internet explorer browser in the order, one after one.If you want to run all these 3 tests concurrently in 3 browsers respectively, make parallel="tests" in the TestNG's configuration file.

    Monday, January 02, 2012

    Problem Running Selenium Testcase on firefox 8

    Problem,
    Selenium test stop working, the test launches firefox and freezes forever.

                When i have updated my  Firefox  to version 8 and then tried to run my Selenium tests through the Selenium RC, it launch the first instance of Firefox (the one that logs the Selenium commands) but it didin't launch the actual testing window. So the tests couldn't run. I am using version 2.11.0 of Selenium RC. If you will revert it to Firefox 7 then  the windows will launch fine, and the tests will run.

    Solution,
    Change your version of selenium-server to the latest version.
    Download the latest version of selenium-server jar(selenium-java-<version-number>.jar) from the SeleniumHQ downloads page. Firefox 8 is supposed to be supported since 2.12.