Showing posts with label SeleniumJRunner. Show all posts
Showing posts with label SeleniumJRunner. Show all posts

Saturday, December 20, 2008

Dedicated to developing Selenium Core Firefox chrome branch

Since my team has chosen Selenium Core-Firefox chrome with Selenese table test case as primary Selenium testing method, my task will focus on Selenium Core Firefox chrome branch development(A brand new Selenium-IDE). I will also contribute a bundle of Java APIs to play Selenium Core*ffchrome. Moreover, I should provide a GRID framework for huge test case number run.

"Simply the best". No proxy server, no Remote Control, no IE/HTA, no Java Test Case, no Same Origin Policy, I really found this mode is efficient but powerful as long as we provide an enterprise framework.

For QA, they only need learn Selenese table knowledge without Java programming skills. They don't need to install any complex framework but only setup our Selenium-IDE version on their desktop.

For framework developer, then needn't build a heavyweight infrastructure like proxy server, client driver. What they need do are only:
1) Let Selenium-Core*ffchrome save detailed enough result capture/snapshot with well formed structure to local file system.
2) Extend chrome URL parameters to meet all configuration requirements. We can benifit a lot from Mozilla APIs and do some fantasitic jobs for Selenium core(That why we choose Firefox as Selenium browser).
3) A bundle of Java APIs to play Selenium-Core*ffchrome under isolated profile and parse run results to Java Objects. We can define an atomic unit(1-3) as one Selenium Agent.
4) A GRID Java framework to distribute huge test case number run on Agents with scalability. DB support is necessary to save both test case info and run result info.
5) Then a GUI web based test case maintenance and execution portal is possible with above back end framework supporting.

Comparing to official RC+GRID solution, our solution is more suitable for acceptance test, integrating test & regression test(black box).

Monday, November 17, 2008

Multiple Profiles running simultaneously synchronization in SeleniumJRunner

We must assign each SeleniumJRunner a unique profile name at one time.
Otherwise, if 2 instances use the same profile name at one time, Firefox will report "Firefox is already running..." error.

Assume we have pre-created Firefox profiles on one machine with name:
testprofile1
testprofile2
testprofile3
...
testprofile9

We can lock profile name when one SeleniumJRunner is using it and unlock it when SeleniumJRunner quit. If there is no free profile name, let new SeleniumJRunner wait.

Sample code:
public static String lockAndGetAvailableProfile(String[] allProfiles) { 
  FileLock lock = null; 
  for (int i = 0; i < allProfiles.length; i++) {
   try {
    RandomAccessFile raf = new RandomAccessFile(PROFILE_LOCK_FOLDER 
                        + "/" +i+".lck" , "rw");
    FileChannel fileChannel = raf.getChannel();
    lock = fileChannel.tryLock();
    if(lock != null && lock.isValid()
       && !lock.isShared()){ 
     return allProfiles[i];
    }else{
     lock = null;
     fileChannel.close();
     raf.close();
    }
   } catch (IOException ioe) {
    ioe.printStackTrace();
   } 
  }
  return "No available profile";
}

Saturday, November 15, 2008

Customize Selenium Chrome TestRunner profile in JRunner

There is a prefs.js configuration file for each Firefox profile.
Selenium Java Runner can do some necessary customization before launch Firefox TestRunner instance.
Read prefs.js docs: http://kb.mozillazine.org/Prefs.js_file

Sample prefs.js customize code:
PrintStream out = new PrintStream(new FileOutputStream(prefsJS, true));
// Don't ask if we want to switch default browsers
out.println("user_pref('browser.shell.checkDefaultBrowser', false);"); 
// suppress authentication confirmations
out.println("user_pref('network.http.phishy-userpass-length', 255);");
// Disable pop-up blocking
out.println("user_pref('browser.allowpopups', true);");
out.println("user_pref('dom.disable_open_during_load', false);");
out.println("user_pref('startup.homepage_welcome_url', '');");
// Disable Restore your session dialog. Always start a new session
out.println("user_pref('browser.sessionstore.enabled', false);");
// Disable security warnings
out.println("user_pref('security.warn_submit_insecure', false);");
out.println("user_pref('security.warn_submit_insecure.show_once', false);");
out.println("user_pref('security.warn_entering_secure', false);");
out.println("user_pref('security.warn_entering_secure.show_once', false);");
out.println("user_pref('security.warn_entering_weak', false);");
out.println("user_pref('security.warn_entering_weak.show_once', false);");
out.println("user_pref('security.warn_leaving_secure', false);");
out.println("user_pref('security.warn_leaving_secure.show_once', false);");
out.println("user_pref('security.warn_viewing_mixed', false);");
out.println("user_pref('security.warn_viewing_mixed.show_once', false);");
// Disable cache
out.println("user_pref('browser.cache.disk.enable', false);");
out.println("user_pref('browser.cache.memory.enable', true);");
// Disable "do you want to remember this password?"
out.println("user_pref('signon.rememberSignons', false);");
// Disable any of the random self-updating crap
out.println("user_pref('app.update.auto', false);");
out.println("user_pref('app.update.enabled', false);");
out.println("user_pref('extensions.update.enabled', false);");
out.println("user_pref('browser.search.update', false);");
out.println("user_pref('browser.safebrowsing.enabled', false);"); 
//enable javascript 
out.println("user_pref('javascript.enabled', true);"); 
//Optional Tips: User-Agent hijack for http traffic debug
//out.println("user_pref('general.useragent.override', 'Here crack user-agent');");  out.close();

Saturday, November 8, 2008

How to let JAVA play with Selenium Firefox Chrome TestRunner

Selenium Firefox Chrome TestRunner is written by JS/DHTML. When we want to embed Firefox Chrome TestRunner engine into our testing framework. We are asking for a way to let JAVA play with Firefox Chrome TestRunner. You can also refer to Selenium-RC source code to launch a browser. Here is a workaround solution with pseudo code.

1. In & Output of 'Selenium Firefox Chrome TestRunner' component for JAVA IN: it is usually URL trigger for running. Chrome URL with parameters looks like:
chrome://selenium-ide-testrunner/content/selenium/TestRunner.html?test=file:///c:/testing/MyTestSuite.html&auto=true&multiWindow=true&userExtensionsURL=http://localhost/user-extensions.js,http://localhost/ui/my-ui-map.js&close=true&[other self defined parms]
We can see Selenium passed parameters by chrome URL for input. We can add more self defined params by modify Selenium-IDE code.
If we can convert all parameters in JAVA to chrome URL parameters, it's possible to let JAVA invoke Selenium-IDE.

OUTPUT: one output choice provided by S-CORE is using POST data when Selenium closed. It required you create a server side receiver.
One better solution is S-IDE save run snapshot/result/log runtimely to file system directly. We treat these important data as output.

For offical docs about IN&OUTPUT, refer to http://seleniumhq.org/projects/core/usage.html

2. 'IN' Wrapper in JAVA
We create a Java Object as a chrome URL paramters wrapper, simple like:
public class SeleniumRequest implements Serializable {
 private String test; 
 private String auto;
        private String multiWindow;
...
        public String getAuto() {
  return auto;
 } 
 public void setAuto(String auto) {
  this.auto = auto;
 }
...
}
3. 'OUTPUT' Wrapper in JAVA
We also create a Java Object as atomic run result wrapper, simple like:
public class SeleniumResult implements Serializable {
 private int testRuns; 
 private int testFailures; 
        private String resultSummary;
 private String logFilePath;  
...
        public String getResultSummary() {
  return resultSummary;
 } 
 public void setResultSummary(String resultSummary) {
  this.resultSummary= resultSummary;
 }
...
}
Detailed run results are saved on file system by S-IDE. logFilePath is the path for their index file.

4. SeleniumJRunner in Java
Now, we can define a very simple & generic interface for run S-IDE in Java.
public interface SeleniumJRunner {
      public SeleniumResult run(SeleniumRequest request); 
}
We assume this run API is sync mode, which means run() will be blocked in Java thread until S-IDE finished run and generate OUTPUT.

5. SeleniumResultParser.java
S-IDE saved all results in file system, we need a Java class to parse file content and set to SeleniumResult object. This is part of SeleniumJRunner implementation logic. To do html file parser in Java, there are many opensource lib. You can use Nekohtml.

6. SyncExecutor.java
Since S-IDE is an external process for Java. We need launch it with parameters from Java in sync mode. Usually, JAVA API Runtime.getRuntime().exec() meets basic requirement. However, we need a timedout mechanism and safely execution which Runtime.getRuntime() doesn't provide. We create a powerful but simple SyncExecutor util. For related topic, refer to how to safely execute process from java

7. Launch Selenium with profile isolation on the same machine
It is super Firefox can run multiple instances with session/cache isolation concurrently on the same machine by Firefox Profiles mechanism.
We need to add -p ProfileName -no-remote parameters to Firefox cmdline.
For multiple Firefox profiles run together, refer to http://clan.yo2.cn/run-multiple-firefox-profiles-simultaneously.html

8. There is critical issue for launch Chrome TestRunner in cmdline mode
User may encounter weird issue if launch Chrome TestRunner in cmdline like firefox.exe -chrome "chrome://selenium-ide-testrunner/content/selenium/TestRunner.html..." . It's hard to resolve. In JRunner, we must choose a workaround substitution.
For solution, read topic: http://clearspace.openqa.org/message/51801#51801