Sunday, September 26, 2010

Create WaterFall Chart for Performance (Duration)

usually, I wanna know how much load created at certain point of time on my async system, and see how much impact the concurrent load bring to it. So I made a simple Create WaterFall Chart to help me to understand these more clearly.
This is written in Ruby,sorry java guys, it is faster for me to write ruby code than java, but i like java gradually :-)

I am using Google Chart API, Googlecharts, TinyURL services, Thanks you for providing these!

A quick snapshot for waterfall chart(click to see big):




Test code:

 require 'gchart'  
 require 'time'  
 require 'open-uri'  
 require 'uri'  
 require 'accessDB'  
 #Get start and end time stamp from DB  
 startArray = ["2010-09-26 16:58:37.693","2010-09-26 16:58:38.223","2010-09-26 16:58:38.833",  
 "2010-09-26 16:58:39.600","2010-09-26 16:58:40.210","2010-09-26 16:58:40.833","2010-09-26 16:58:55.740"];  
 endArray = ["2010-09-26 16:59:56.543","2010-09-26 16:59:58.183","2010-09-26 17:00:04.217",  
 "2010-09-26 17:00:09.370","2010-09-26 17:00:10.217","2010-09-26 17:00:19.323","2010-09-26 17:00:25.027"];  
 Gchart_string = prepareData(startArray, endArray )  
 Gchart_url = waterFallUrl(Gchart_string)  
 puts minifyUrl(Gchart_url)  

Prepare Google chart Data and para:
 def prepareData(starttime, endtime )  
  if starttime.length > 400  
   puts "\nExceed the maxium number(400) of records."  
   puts "You can try to split them to display.Press Enter to exit..."; $stdout.flush  
   gets  
   break;  
  end  
  # convert Time Object string to Time object Int  
  starttime.collect! { |time1|  
  Time.parse("#{time1}").to_i;  
  }  
  starttime.sort!  
  endtime.collect! { |time2|  
   Time.parse("#{time2}").to_i;  
  }  
  endtime.sort!  
  # prepare data in array, convert to string used by Gchart  
  flag = starttime[0]  
  starttime.collect! { |time1|  
   time1-flag;  
  }  
  endtime.collect! { |time2|  
   time2-flag;  
  }  
  if endtime.last > 3600  
   puts "\nWarning: Duration is too long to display well for Chart(3600s is recommended).";  
   puts "You can split the data to display."  
  end  
  line_xy_string = "";  
  scale_num = 1;  
  cata = 10;  
  while endtime.last > cata  
   cata = cata + 10 ;  
  end  
  scale_num = cata/starttime.length  
  starttime.length.times { |i|   
   line_xy_string << starttime[i].to_s;  
   line_xy_string << ",";  
   line_xy_string << endtime[i].to_s;  
   line_xy_string << "|";  
   line_xy_string << ((i+1)*scale_num).to_s + "," + ((i+1)*scale_num).to_s;  
   # ignore the last "|"  
   if ((i+1) < starttime.length)  
    line_xy_string << "|";  
   end  
  }  
  line_xy_string << "&chds=";  
  line_xy_string << "0,#{cata}";  
  line_xy_string << "&chxt=x,x,y"  
  line_xy_string << "&chxr=0,0,#{cata}"  
  line_xy_string << "&chxl=1:|Duration(sec)"  
  return line_xy_string;  
 end  


Get Google Chart URL:
 def waterFallUrl(chart_string)  
  output_url = Gchart.line_xy(:size => '700x400',  
       :title => "WaterFall Charts",  
       :custom => "chd=t:#{chart_string}")  
  #"&chxr=0,0" is automatic added to the end of string,  
  #remove it due to already identify one in chart_string  
  output_url.chomp!("&chxr=0,0");  
  return output_url  
 end  

Minify URL using tinyURL:
 def minifyUrl(gchartUrl)  
  # convert URL to escaped one  
  escaped_url = URI.escape(gchartUrl, Regexp.new("[^#{URI::PATTERN::UNRESERVED}]"))  
  short_url = open("http://tinyurl.com/api-create.php?url=#{escaped_url}").read  
  return short_url;  
 end  

Also if you have written a data query method to get start and end time from DB, then it is easy to get startArray and endArray directly by T-SQL. i am using this in practice: http://snippets.dzone.com/posts/show/3906

or you may take look at this, FYI:
 require 'win32ole'  
 class SQLServer  
   # This class manages database connection and queries  
   attr_accessor :connection, :data, :fields  
   attr_writer :username, :password  
   def initialize(host, username = 'sa', password='sa')  
     @connection = nil  
     @data = nil  
     @host = host  
     @username = username  
     @password = password  
   end  
   def open(database)  
     # Open ADO connection to the SQL Server database  
     connection_string = "Provider=SQLOLEDB.1;" #SQLOLEDB.1,SQLNCLI  
     connection_string << "Persist Security Info=False;"  
     connection_string << "User ID=#{@username};"  
     connection_string << "password=#{@password};"  
     connection_string << "Initial Catalog=#{database};"  
     connection_string << "Data Source=#{@host};"  
     connection_string << "Network Library=dbmssocn"  
     @connection = WIN32OLE.new('ADODB.Connection')  
     @connection.Open(connection_string)  
   end  
   def query(sql)  
     # Create an instance of an ADO Recordset  
     recordset = WIN32OLE.new('ADODB.Recordset')  
     # Open the recordset, using an SQL statement and the  
     # existing ADO connection  
     recordset.Open(sql, @connection)  
     # Create and populate an array of field names  
     @fields = []  
     recordset.Fields.each do |field|  
       @fields << field.Name  
     end  
     begin  
       # Move to the first record/row, if any exist  
       recordset.MoveFirst  
       # Grab all records  
       @data = recordset.GetRows  
     rescue  
       @data = []  
     end  
     recordset.Close  
     # An ADO Recordset's GetRows method returns an array  
     # of columns, so we'll use the transpose method to  
     # convert it to an array of rows  
     @data = @data.transpose  
   end  
   def close  
     @connection.Close  
   end  
 end  

Usage sample:
 db = SQLServer.new('YourDBIP', 'sa', 'sa')  
 sp = db.open('DBName')  
 startArray = db.query("select * from somewhere where ...")  
 endArray = db.query("sselect * from somewhere where ...")  
 db.close  

Monday, September 20, 2010

Handle Datepicker using WebDriver simple sample

Someone asked me: "How to identify a datepicker on the webpage, which will display after clicking the datepicker icon?"
Here is a simple sample, you can customize your own function for reading your web page source and make a api for picking any dates freely :-)

//Find all the Calendar on the Web Page
List<WebElement> Datepickers = driver.findElements(By.className("CalendarIcon"));

//Trigger the calendar of StartDate
driver.manage().timeouts().implicitlyWait(5, TimeUnit.SECONDS);
Datepickers.get(0).click();


WebElement table = driver.findElement(By.className("ui-datepicker-calendar"));

List<WebElement> tds = table.findElements(By.tagName("td"));
for (WebElement td: tds){
//Select 20th Date of current month
if (td.getText().equals("20")){
td.findElement(By.linkText("20")).click();
break;
}

}

//Trigger the calendar of EndDate
driver.manage().timeouts().implicitlyWait(5, TimeUnit.SECONDS);
Datepickers.get(1).click();

WebElement table2 = driver.findElement(By.className("ui-datepicker-calendar"));

List<WebElement> tds2 = table2.findElements(By.tagName("td"));
for (WebElement td2: tds2){
//Select 22th Date of current month
if (td2.getText().equals("22")){
td2.findElement(By.linkText("22")).click();
break;
}

}

Wednesday, September 15, 2010

Table walk through in WebDriver

Very Simple sample for dealing with table elements on webPage in WebDriver:


WebElement table = driver.findElement(By.name("meetingRoomTable"));
//findout all checkboxes within the table
List<WebElement> checkboxes = table.findElements(By.cssSelector("input[type=\"checkbox\"]"));
if (!checkboxes.isEmpty()){
for (WebElement checkbox : checkboxes){

if(!checkbox.isSelected()){
checkbox.toggle();
}
}
System.out.println("all checkboxes elements checked now");
}

else
System.out.println("no checkbox elements exsit on this table");

Sunday, September 12, 2010

Distribute your test suites by STAF(STAX)

STAF is a good Open source "test automation" framework which developed by IBM. I am currently using STAF(STAX) to distribute my test Suites which are organized by TestNG, it is improve your efficiency.

Here is a simple sample how I zip, transfer and execute My Test on 2 machines(please format this XML by yourself, if you need to look at it):

 <?xml version="1.0" encoding="UTF-8" standalone="no"?>  
 <!DOCTYPE stax SYSTEM "stax.dtd">  
 <!-- New document created with EditiX at Fri Jul 09 15:35:49 CST 2010 -->  
 <stax>  
 <script>machinelist = ['Machinename1','Machinename2']</script>  
 <defaultcall function="ZipTest"></defaultcall>  
 <function name="ZipTest">  
 <sequence>  
 <stafcmd>  
 <location>'localhost'</location>  
 <service>'zip'</service>  
 <request>'ADD ZIPFILE D:/Raft_Project/TestPlan.zip DIRECTORY D:/Raft_Project/TestPlan RECURSE RELATIVETO D:/Raft_Project' </request>  
 </stafcmd>  
 <call function="'sleep'"></call>  
 <call function="'DistributionTest'"></call>  
 <call function="'sleep'"></call>  
 <call function="'CleanupTest'"></call>  
 </sequence>  
 </function>  
 <function name="DistributionTest">  
 <paralleliterate var="machinename" in="machinelist">  
 <sequence>  
 <stafcmd>  
 <location>machinename</location>  
 <service>'fs'</service>  
 <request>'DELETE ENTRY D:/Raft_Project/TestPlan RECURSE CONFIRM' </request>  
 </stafcmd>  
 <call function="'sleep'"></call>  
 <stafcmd>  
 <location>'local'</location>  
 <service>'fs'</service>  
 <request>'COPY FILE D:/Raft_Project/TestPlan.zip TODIRECTORY D:/Raft_Project/ TOMACHINE %s' % machinename </request>  
 </stafcmd>  
 <call function="'sleep'"></call>  
 <stafcmd>  
 <location>machinename</location>  
 <service>'zip'</service>  
 <request>'UNZIP ZIPFILE D:/Raft_Project/TestPlan.zip TODIRECTORY D:/Raft_Project/'</request>  
 </stafcmd>  
 <call function="'sleep'"></call>  
 <stafcmd>  
 <location>machinename</location>  
 <service>'fs'</service>  
 <request>'DELETE ENTRY D:/Raft_Project/TestPlan.zip RECURSE CONFIRM'</request>  
 </stafcmd>  
 <process>  
 <location>machinename</location>  
 <command mode='"shell"'>'Runner.bat'</command>  
 <workdir>R'D:\Raft_Project\TestPlan\TestRunner_Module1'</workdir>  
 <returnstdout/>  
 <returnstderr/>  
 </process>  
 </sequence>  
 </paralleliterate>  
 </function>  
 <function name="CleanupTest">  
 <stafcmd>  
 <location>'localhost'</location>  
 <service>'fs'</service>  
 <request>'DELETE ENTRY D:/Raft_Project/TestPlan.zip RECURSE CONFIRM'</request>  
 </stafcmd>  
 </function>  
 <function name="sleep">  
 <stafcmd>  
 <location>'localhost'</location>  
 <service>'delay'</service>  
 <request>'delay 6000'</request>  
 </stafcmd>  
 </function>  
 </stax>  
hope it helps! More detail instruction, please go to STAF official website:http://staf.sourceforge.net/

PS: you may need to modify your under STAF/bin/, so that it can avoid some restrictions.
 # Turn on tracing of internal errors and deprecated options  
 trace enable tracepoints "error deprecated"  
 # Enable TCP/IP connections  
 interface ssl library STAFTCP option Secure=Yes option Port=6550  
 interface tcp library STAFTCP option Secure=No option Port=6500  
 # Set default local trust  
 #trust machine local://local level 5  
 trust default level 5  
 # Add default service loader  
 serviceloader library STAFDSLS  
 SERVICE STAX LIBRARY JSTAF EXECUTE \  
 D:/STAF/services/stax/STAX.jar OPTION J2=-Xmx384m  
 SERVICE EVENT LIBRARY JSTAF EXECUTE \  
 D:/STAF/services/stax/STAFEvent.jar  
 SET MAXQUEUESIZE 10000  
 SERVICE Cron LIBRARY JSTAF EXECUTE D:\STAF\services\cron\STAFCron.jar  

WebDriver Wait is easier after using implicitlyWait()

"WebDriver will wait until the page has fully loaded (that is, the "onload" event has fired) before returning control to your test or script."
The classic example is Javascript starting to run after the page has loaded (onload); while if the website is very "rich", it is always hard for WebDriver to identify some elements by its own blocking API.

Previous solution mentioned/suggested by experts are : Use the Wait class to wait for a specific element to appear:http://groups.google.com/group/webdriver/browse_thread/thread/50c963cd25fb416c/61aae67b8a2560fd?#61aae67b8a2560fd

Here is one example, which i wrapped the presenceOfElementLocated():

 import org.openqa.selenium.By;  
 import org.openqa.selenium.WebDriver;  
 import org.openqa.selenium.WebElement;  
 import org.openqa.selenium.support.ui.WebDriverWait;  
 import com.google.common.base.Function;  
 public class MyWaiter {  
      private WebDriver driver;  
      public MyWaiter(WebDriver driver){  
           this.driver = driver;  
      }  
      public WebElement waitForMe(By locatorname, int timeout){  
           WebDriverWait wait = new WebDriverWait(driver, timeout);  
           return wait.until(MyWaiter.presenceOfElementLocated(locatorname));  
      }  
      public static Function<WebDriver, WebElement> presenceOfElementLocated(final By locator) {  
           // TODO Auto-generated method stub  
           return new Function<WebDriver, WebElement>() {  
                @Override  
                public WebElement apply(WebDriver driver) {  
                     return driver.findElement(locator);  
                }  
           };  
      }  
 }  

My test code:
 public static void main(String[] args) {  
           WebDriver driver = new FirefoxDriver();  
           driver.get("http://www.google.com/");  
           MyWaiter myWaiter = new MyWaiter(driver);  
           WebElement search = myWaiter.waitForMe(By.name("btnG"), 10);  
           search.click();  
      }  

This way looks a little bit fussy to me, although it works well.

Now, implicitlyWait() gives tests a "KISS" and most importantly, it did solve the problem.

driver.findElement(By.id("signIn")).click();  
driver.manage().timeouts().implicitlyWait(30, TimeUnit.SECONDS);  
driver.switchTo().frame("canvas_frame");  
driver.findElement(By.partialLinkText("Buzz")).click();  
driver.findElement(By.linkText("Cheng Chi")).click();  


You may notice that the first sample code using wait.until(), you have to two wait.until() for each link element, otherwise the code will fail; While the second one, you just add one implicitlyWait() in front of the "Buzz" link.
I do not know why, but it shows that implicitlyWait() is a better choice for locating (ajax) elements.

PS: I marked "in front of" as bold above, which means implicitlyWait() is a kind of registration method, you need to tell Webdriver in advance.

Thursday, September 02, 2010

Check and Set Isolation level in SQL Server

Check isolation level:
DBCC useroptions


Default Isolation level in SQL Server is "READ COMMITTED", Once you want to change it:

For example, Set isolation level to READ UNCOMMITTED
SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED

Wednesday, September 01, 2010

Switching Frame and Windows in WebDriver sample code

1> Switch to different Frames:
 List<WebElement> frameset = driver.findElements(By.tagName("frame"));  
 if(frameset.size()>0) {  
 for (WebElement framename : frameset){  
 System.out.println("frameid: " + framename.getAttribute("name"));  
 }  
 }  
 else System.out.println("can not find any frame in HTML");  

Notice when you set the frame index, it starts with 0 for the first frame:
 driver.switchTo().frame(0);  


2> Switch to different Windows:
 Set<string> handlers = driver.getWindowHandles();  
 if (driver.getWindowHandles().size()>= 1){  
 for(String handler : handlers){  
 driver.switchTo().window(handler);  
 if (driver.getCurrentUrl().contains("Popup")){  
 System.out.println("Get focus on Popup window");  
 break;  
 }  
 }  
 }  
 else System.out.println("No windows founded!");  


Writing a common function based you own app for switching will be more helpful for your Code Clean!