Monday, December 27, 2010

Selenium full-fledged implementation

Selenium full-fledged implementation.

In order to implement full-fledge selenium for a project, you may require understanding on following tools and framework.

1. Selenium Core
2. Selenium RC
3. Java (Extending Classes and Implementing Interface)
4. Java Script
5. Eclipse IDE
6. TestNG
7. JUnit
8. Apache Ant
9. AutoIt V3
10. Flex-Pilot
11. Hudson-CI
12. Selenium GRID (optional)

---

Thursday, December 23, 2010

SeleniumRC -Flex/Flash Automation

SeleniumRC -Flex/Flash Automation

Automation of flex is very challenging when compared with normal HTML. As per my understanding no automation tool can recognize the flex objects directly without compiling the flex source code with additional libraries.

All the HTML objects are visible under page DOM, but the flex objects are not visible. Flex is displayed on the page by embedding .swf file in the HTML. As .swf file is proprietary to Adobe and having their own standards and design, object methods are not visible and understood outside. To expose the objects, we need to recompile the flex with some third party libraries.

Points to be considered while selecting third party OR open source libraries.
1. There should be slight increase of .swf file size (or Total Page Size) after the compilation with the additional libraries. This will impact the application performance when multiple users are accessing the page.
2. It should allow to test Flex and Html simultaneously.
3. It should not break the existing functionality and allow us to test in production and test environment.
4. Ability to expose all the flex objects (like Grid...)
5. Easy to code and identify the objects, instead of writing lengthy statements.

Some of the flex libraries for selenium are
1. flash-selenium
2. flexmonkium
3. flex-pilot

I have spent time on above said libraries and felt Flex-pilot is suitable to me. It has bootstrapeer to make application testable and use chains to identify the objects, similar to xpath.

Implementing Flex-pilot on your application, select this Link.
Make sure you don't have any compilation errors and deploy it on test environment.

Test whether flex-pilot bindings are created properly.
1. By using Sauce IDE. Download from this Link. (Firefox add-on)
2. By using firebug

Sauce IDE
Download and install as Firefox add-on. This is similar to Selenium IDE with additional Flex capabilities. It has got "FlexExplorer" that can locate the Flex object chains (xpath for flex-pilot). Open the application and navigate to flex component page, open the Sauce IDE, select the "FlexExplorer" button and locate any flex object, you should be seeing its chain. It is similar to GUI spy in QTP.
Attaching the screen shot for more clarity.

If it find Target value, then that is the main handle. Attaching the screen shot for more clarity.

Firebug
Best way to test your Flex code is by using the Firebug. Flex pilot bindings expose the flex objects methods in the page dom, so by using JavaScript you can simulate the changes on the flex screen without running the code through selenium.
From the above screen you can notice that "GepCatalog" is the main handle for the entire flex object. Type the following code in the firebug console and run it, if it says "Function" every thing is configured perfectly.
Attaching the screen shot for more clarity.

Following are the available API's, select this link.

You can get the object ids from the Flex explorer or flex developer can provide the ids for the objects you are planning to interact. Before moving to selenium, run the DOM script and make sure all the objects are identifiable. Attaching the screen shot for more clarity.

I hope you are comfortable identifying the flex objects, lets move to selenium.
You can run the same above methods in selenium in the following way.
s.runScript("document.getElementById('GepCatalog').fp_type({name:'txtSearch', text:'laptop'})");
s.runScript("document.getElementById('GepCatalog').fp_click({name:'goBtn'})");
If you want to run by using selenium directly without using page DOM.
Download "DefaultSelenium.Java" from the from this link, implementation of Selenium interface with additional flex methods.
Download "UserExtension.js" from this Link and run the selenium jar using this extension. For more details read this Post.
There will be slight change in the code, Selenium code looks like this.
private Selenium s = new ds( "localhost",4444,"*iexplore",BASE_URL);
---
((ds)s).flexType("id=GepCatalog", "text=laptop,chain=name:txtSearch");
((ds)s).flexClick("id=GepCatalog", "chain=name:goBtn");
Note: ds - DefaultSelenium.Java

Thanks a lot for Flex-Pilot contributors.
Enjoy Flex, Happy Testing!
---

Thursday, December 16, 2010

Selenium - Simulate Modal Dialog Pop-Up

Selenium - Simulate Modal Dialog Pop-Up

when user open a Modal dialog pop-up by selecting a link or button, focus on the parent window is lost and user is forced to act on the pop-up window and close it, before proceeding further. User can't even look at page view source during modal pop-up on the screen.

Selenium work by executing the JavaScript, when pop-up is displayed, parent window JavaScript execution capability is lost, naturally Selenium can't work.

What are the issues I came across?
1. I am not able to open the Modal Pop-Up using selenium, when I select the link I am getting error message, it work fine when I open the window manually with out Selenium. My Modal pop-Up contain complex Ajax functionality that is conflicting with the Selenium Core when I select the pop-up link.
Attaching error screen shot for more clarity.

2. Values returned by the pop-up are mandate fields, I cant submit the page without these values.

I started searching in Google, but there is no solution. I do not have enough time to debug the selenium core and understand why it is conflicting with the application. Need to some how manage with out opening the pop-up. Then I started looking at the view source and understood the return values of the pop-up.
Attaching screen shot of the call statement to modal pop-up from page view source.


                          
Then I though, why can't I update the values directly in the page DOM, so that it is not even required to open the pop-up. Then I could succeed injecting the values and simulated the modal pop-up dialog.
Attaching the Selenium code
String JS =
               "{" +
               " this.page().findElement('id=ctl00_Cphe_txtSuppName').value='Supplier1';" +
               " this.page().findElement('id=ctl00_Cphe_hdnVendorId').value='1267';" +
               " this.page().findElement('id=ctl00_Cphe_hdnContactId').value='233';" +
               "}"; 
      s.getEval(JS);
I hope this post can help people having issues with modal pop-up.
Enjoy!


Monday, December 6, 2010

Selenium UserExtension - RC vs IDE

Selenium UserExtension - RC vs IDE

There are slight differences between Selenium RC and IDE JavaScript functions. Below example will help you in converting the function from one format to another.

Timer extension for IDE from Wiki Link.
var globalTime = new Object();
Selenium.prototype.doTimerStart = function(target) {
 var dt1 = new Date();
 if (target == null || target == "")
 {
  LOG.info ("Target not present so timer was not started");
 } else {
  globalTime[target] = dt1;
 }
 delete dt1;
};
Selenium.prototype.doTimerStop = function(target) {
 var dt = new Date();
 if (target == null || target == "")
 {
  LOG.info ("Please specify a target");
 } else if (globalTime [target] == null) {
  LOG.info ("Start time was not called for " + target);
 } else {
   LOG.info ("Time Passed for " + target + " : " + Math.floor (
dt - globalTime[target]));
  delete globalTime[target]; }
 delete dt;
};

The same above functions converted into RC format
var globalTime = new Object();
Selenium.prototype.getTimerStart = function(target) {
 var dt1 = new Date();
 if (target == null || target == "")
 {
  return  ("Target not present so timer was not started");
 } else {
  globalTime[target] = dt1;
  return null;
 }
 delete dt1;
};

Selenium.prototype.getTimerStop = function(target) {
 var dt = new Date();
 if (target == null || target == "")
 {
  return  ("Please specify a target");
 } else if (globalTime [target] == null) {
   alert("called");
  return  ("Start time was not called for " + target);
 } else {
   return  ("Time Passed for " + target + ":" + Math.floor (dt - globalTime[target]) + " msec");
   delete globalTime[target]; 
  }
 delete dt;
};

How to call this function from Java, read this Link.

---

Thursday, December 2, 2010

Selenium timer extension

Selenium timer extension

Selenium don't provide built in timer objects to calculate the page response time or page load time.
You need to extend the functionality by using Java script or by Java language.

Selenium timer extension for IDE is provided at Link.
Above Java script don't work on Selenium RC, so I have modified the Java Script and placed in the following Link.

I prefer using timers in Java language, you can find the sample code in this Link.

---

Selenium RC - User Extension.JS

Selenium RC - User Extension.JS

As a Selenium programmer you may require to create new methods or functions that doesn't exist.
One of the best method is by using UserExtension.js. In future posts I will explain about extending the existing selenium class.

Add following libraries to your project, attaching the snap shot.


Create new java class using following code. This example is created on google.com, so that any one can execute the code with out any issues.

What is this program about ?
1. Created new Method "MyClick".
2. Two new functions to calculate page response time (timerStart, timerStop).
3. Open the google page, search for an item and display page response time in Milli seconds for the results page.
Initially I had lot of issues while working with user-extensions, I want to bring clarity to my users by providing this example. There are differences between IDE and RC extensions, read my timer extension post for better understanding.

package package1;

import static org.testng.AssertJUnit.*;
import org.testng.annotations.*;
import com.thoughtworks.selenium.*;


public class Sample2
{
    private static final String Timeout = "30000";
    private static final String BASE_URL = "http://google.com/";
    private static final String BASE_URL_1 = "/";
    private Selenium selenium;
    private HttpCommandProcessor proc;
    
    @BeforeClass
    protected void setUp()throws Exception
    {
       proc = new HttpCommandProcessor("localhost", 4444, "*iexplore", BASE_URL);
       selenium = new DefaultSelenium(proc);     
       selenium.start();
       selenium.windowFocus();
       selenium.windowMaximize();
       selenium.windowFocus();
    }
    
    @AfterClass(alwaysRun=true)
    protected void tearDown() throws Exception
    {
       selenium.stop();
    }
    
    @Test(groups="search")
    public void test_GoogleSearch() throws Exception
    {
     selenium.open(BASE_URL_1);
     selenium.type("name=q", "selenium HQ");
     System.out.println(proc.doCommand("getTimerStart",new String[] {"GooglePage"}));
     //selenium.click("btnG"); //selenium command 
     proc.doCommand("myClick",new String[] {"btnG"}); //user extension for Click ()
     selenium.waitForPageToLoad(Timeout);
     System.out.println (proc.doCommand("getTimerStop",new String[] {"GooglePage"}));
     Thread.sleep(5000); //Show the page for few seconds 
    }
    @Test(groups="search")
    public void test_GoogleSearch1() throws Exception
    {
     selenium.open(BASE_URL_1);
     selenium.type("name=q", "Bharath Marrivada");
     System.out.println(proc.doCommand("getTimerStart",new String[] {"GooglePage"}));
     //selenium.click("btnG"); //selenium command
     proc.doCommand("myClick",new String[] {"btnG"}); //user extension for Click ()
     selenium.waitForPageToLoad(Timeout);
     System.out.println (proc.doCommand("getTimerStop",new String[] {"GooglePage"}));
     Thread.sleep(5000); //Show the page for few seconds 
    }    
}



UserExtension.js

Selenium.prototype.doMyClick = function(inputParams) 
{
 var element = this.page().findElement(inputParams);
 this.page().clickElement(element);
 return null;
};

var globalTime = new Object();
Selenium.prototype.getTimerStart = function(target) {
 var dt1 = new Date();
 if (target == null || target == "")
 {
  return  ("Target not present so timer was not started");
 } else {
  globalTime[target] = dt1;
  return null;
 }
 delete dt1;
};

Selenium.prototype.getTimerStop = function(target) {
 var dt = new Date();
 if (target == null || target == "")
 {
  return  ("Please specify a target");
 } else if (globalTime [target] == null) {
   alert("called");
  return  ("Start time was not called for " + target);
 } else {
   return  ("Time Passed for " + target + ":" + Math.floor (dt - globalTime[target]) + " msec");
   delete globalTime[target]; 
  }
 delete dt;
};
Note: Make sure you create the .js file in the selenium.jar folder.

To execute JavaScript functions from .js file, need to use  http command processor "proc.doCommand".
If the function is not returning any value start the function name with "do", else use "get".
Function names are case sensitive, always start with lower case. For "do" function, remove "do" while calling the function from Java.

To start the selenium server use following command.
java -jar selenium-server.jar -userExtensions user-extensions.js

To start the Selenium server quickly, every time instead of going into command prompt, I use following text saved as .vbs file. Double click the file, your selenium server will be up and running. (Modify the folder path)
Dim oShell
Set oShell = WScript.CreateObject ("WScript.Shell")
oShell.run "cmd /K CD C:\selenium-remote-control-1.0.3\selenium-server-1.0.3 & java -jar selenium-server.jar -userExtensions user-extensions.js"
Set oShell = Nothing

Enjoy!

For more information look at selenium documentation.
---

Wednesday, December 1, 2010

Selenium Documentation

Selenium Documentation