21.8.15

Maven command cheatsheet

All commands to be executed from the project root folder containing the pom.xml

mvn help:effective-pom
Displays a much larger POM which exposes the default settings of Maven.

mvn jar:jar
This packs up [creates a package] the entire project into a .JAR file, and places it under {basedir}/target folder, with a name like 'BDD-1.0-SNAPSHOT.jar'.
This can be used to zip-up the projects and move around.

mvn site
This will execute the site lifecycle phase. This lifecycle is concerned solely with processing site content under the src/site directories and generating reports. After this command executes, you should see a project web site in the target/site directory. Load target/site/index.html and you should see a basic shell of a project site. 
You can customize site reports by configuring which reports are included in a build via the pom.xml file. JBehave uses this feature to create those result reports, and the format of those reports is implemented via .FTL files.

mvn dependency:resolve
This will list down all the dependencies [jars, versions, etc], and their scope, including the implicit transient [child] dependencies.

mvn dependency:tree
This will list down all the dependencies in your pom, along with the transient dependency for each of those - which dependency in your pom has its own implicit child dependency.

mvn install assembly:assembly
In this the 'assembly' goal is executed by the 'assembly' plugin, after the Maven build reaches the 'install' lifecycle phase. This shows an example of commands using life-cycle phases and plugin goals.

mvn clean > clean.txt
This will run the clean command and output the result text in the clean.txt file in the root dir.



4.8.15

Pass and read Runtime Property Values via Maven command

Many a times when you implement CI with Maven & Jenkins or TeamCity, you might want to pass parameters to the test like the Browser and Env in which you want to run your tests.
This can be done in various ways, but a very simple and straightforward method is as follows -

Define the variables in your tests that you want to store the values of these run-time parameters, like below

static final String BROWSER_TYPE = System.getProperty("browserType");
static final String RUN_ENV = System.getProperty("runEnv");

These can be defined in the base Abstract class that you use to initialize global methods/fields, etc. And its a good idea to declare them static and final so that we can use them directly in our tests, and we dont overwrite these values.

System.getProperty - this is the method that actually gets you the value that you have passed as part of your maven command. You can get any property you want via this.

Your maven command can look like this -

    mvn integration-test -DbrowserType=chrome -DrunEnv=test3

You can have these parameters defined in any order, and can give any name to it, but the names passed as maven command, and those referred in your tests should be the same. What I refer here as parameters is technically called a property of the plugin.

In order to pass multiple values for the same parameters, use the following syntax -

mvn integration-test -DbrowserType=FireFox-DrunEnv=Test1 -DmetaFilters=+Regression +OnBoarding -skip -Manual -wip

Multiple values have been specified for the metaFilters property, to be used with JBehave Test Story-s and Scenarios.
This will only execute scenarios with Regression and OnBoarding tags, and not with skip, Manual or wip tags. Refer this post to learn more about Meta Filtering with JBehave

Another example of maven parameters -

mvn clean integration-test 
-Duse.sso.login=true 
-Dcontext.view.show=false 
-Dusers.dir="c:\jenkins\jbehave" 
-Dbrowser=firefox -Denv=test1 
-Dmeta.filters="${PARM_META_FILTERS} -broken -wip -skip -manual"


We can declare parameter names like ${suiteXmlLFile} in the POM and then specify that in the mvn command to pass the value at run time.
<suiteXmlFile>${suiteXmlFile}</suiteXmlFile>

mvn test -DsuiteXmlFile=./Config/parallelTestNG.xml

Maven commands are case sensitive hence, use exact names while specifying and reading values.


One cool trick is that you can validate the value that was passed via maven correctly or not, by looking up that property [browserType] in the 'System Properties' pane of JVisualVM for your IDE - intelliJ or Eclipse.

26.7.15

Cross Browser Testing with Selenium

When it comes to CBT [ or Browser Compatability Testing], there are 2 broad aspects

1. Ensuring that functional features of your web site work
2. Ensuring that the layout of your web site is consistent across browsers

If its an internal app and only needs to be tested for a few major browsers and limited versions, then we can easily do this with Selenium; by running our automated functional tests on these different browsers by using the driver of each browser. See my earlier post on how to run tests on different browsers.
In most cases, this should suffice, because it will easily uncover any glaring issues - and they are mostly with JavaScript and IE. The other thing that you would notice is that the same website, runs fastest in Chrome, then Firefox and slowest in IE.

This still leaves out the layout part though. For that, we can use the free library called FighthingLayoutBugs from Google, but even that project is dead as of May 2015 because the only contributor on this project quit!

I still tried to use it though, but its a little flaky and gives large false negatives - you can still try and run it and see what results it gives for your website. But now since its dead, there is no point in using it any more, because future browser versions will not be supported.

Here is a code snippet for playing around with FighthingLayoutBugs. 
Also, remember to download the jar with all the dependencies, and not just the standalone jar [even if you have selenium jars already] because FLB has some additional dependencies that are not documented, and are only available in the 'full' version. 
Also, you will not  be able to download it via maven dependency, since the project is defunct, so add the jar to your class path manually.

import com.googlecode.fightinglayoutbugs.FightingLayoutBugs;
import com.googlecode.fightinglayoutbugs.LayoutBug;
import com.googlecode.fightinglayoutbugs.WebPage;
import org.openqa.selenium.WebDriver;
import org.testng.annotations.Test;
import java.util.Collection;

public class CrossBrowserTestDemo {

    @Test
    public void cbtDemo() {

        WebDriver driver;
        Drivers allDrivers = new Drivers("chrome");
        driver = allDrivers.getDriver();

        String baseURL = "http://www.goolge.com";

        driver.get(baseURL);

        WebPage webPage = new WebPage(driver);

        FightingLayoutBugs fightingLayoutBugs = new FightingLayoutBugs();

        final Collection<LayoutBug> allLayOutBugs = fightingLayoutBugs.findLayoutBugsIn(webPage);

        System.out.println("Number of LayoutBugs found = " + allLayOutBugs.size());

        for (LayoutBug bug : allLayOutBugs) {
            System.out.println(bug);
        }
    }
}   //end of class CrossBrowserTestDemo



Now to deal with the item #2 - If its an external customer facing web site, then the scope of CBT increases drastically - by one account there 260 different browser versions being used globally, and across 3 different OS-es. If you want to certify your website even on 10% of the browsers, across 2 OS-es, it would be a herculean task to get this kind of infrastructure setup in house - no company has such a budget, and specially not for testing! Even if you had someone bankrolling you on this, the effort required to manage such an infrastructure would be prohibitive - you just cannot do this in-house!

But luckily, there are various companies that provide this infrastructure on pay-per-use basis, for as low as 20$/month, and this looks like a more pragmatic approach. Read this for more info.

22.6.15

JBehave Archetypes

There are different archetypes available for JBehave, lets look at some of them...


Archetype 1:  jbehave-simple-archetype
URL -

Command to download the project via mvn:
mvn archetype:generate
-DarchetypeGroupId=org.jbehave
-DarchetypeArtifactId=jbehave-simple-archetype
-DarchetypeVersion=3.9.5
-DarchetypeRepository= https://nexus.codehaus.org/content/repositories/releases/org/jbehave/jbehave-simple-archetype/

Comments on this archetype:
  • Change to the latest version
  • This is the most simplest of the project structures that we have with jbehave. Its the default one that I use, and gradually 'build-out' as the project evolves.
  • This does not have the selenium jars by default
  • You can grow this project by adding maven dependencies in the pom.xml
  • You don’t need a selenium-only archetype because we are not going to work on a selenium-only framework, we need a simple archetype to start with, and build it as we grow.




Archetype 2: jbehave-web-selenium-java-spring-archetype
URL -

Command to download the project via mvn:
mvn archetype:generate
-DarchetypeGroupId=org.jbehave.web
-DarchetypeArtifactId=jbehave-web-selenium-java-spring-archetype
-DarchetypeVersion=3.5.5
-DarchetypeRepository= https://nexus.codehaus.org/content/repositories/releases/org/jbehave/web/jbehave-web-selenium-java-spring-archetype/

Comments on this archetype:
  • This has details of implementation for etsy, and is not a blank project like the simple archetype.
  • The implementation appears complex like that of LT
  • It does not seem to recognise the steps, so something is missing. Who knows if its due to the project being 3 years old!
  • This does not have the selenium jars by default
  • There are 3 different 'Stories' file which might be helpful in figuring out the different configurations for jbehave.
  • Also, though the LT framework had jbehave core+web, selenium, fluentlenium, spring, hamcrest and hibernate, you dont have to adopt all of these right now in your framework, because it would be too time consuming to do a PoC with all these. And even then, the LT framework did not have any data-driving capabilities!
  • Spring is a framework that provides APIs to avoid low level coding, for example connecting to a db.
  • Hibernate is a framework for mapping RDBMS or DBs like Sybase, MS SQL Server, etc; where the db tables and entities are exposed as objects that can be used in java code.



Resources -


21.6.15

Working with WebTable in Selenium

This below code with comments demonstrates how we can work with web tables in selenium.

import org.openqa.selenium.By;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.support.FindBy;

import java.util.List;


public class HerokuAppWebTable {


    @FindBy(xpath = ".//*[@id='table1']/thead/tr") private static WebElement tblHeader;

    @FindBy(xpath = ".//*[@id='table1']/tbody") private static WebElement tblBody;

//    @FindBy(xpath = ".//*[@id='table1']/tbody") private static WebElement tblBody;

//    this the webtable from the elemental selenium example. this is a simple td/tr type of table, and not one with DIV tags
//    the body of the table [without its headers] can be located by this xpath = ".//*[@id='table1']/tbody"
//    if we do a getText on this element, we can get the text of the entire table, without the headers
//    the column headers are not part of the table body, hence, the number of rows returned by this method is the actual number of data records present in the table
//    the number of rows in this body of table can be located by this xpath = ".//*[@id='table1']/tbody/tr"
//    to get the number of rows under the body of the table, use a combination of List <WebElement> and findElementsBy methods
//    So, in short, to work with web tables, locate the table body [by building xpath till tbody element], then get the data rows [by locating all elements with tr tag]
//    There is no direct way of working with web tables in selenium, no WebTable element!


//    There is another method to get the number of rows in the table as shown below

//    List<WebElement> rowNum = driver.findElements(By.xpath(".//*[@id='table1']/tbody/tr"));
//    System.out.println("Row Num = " + rowNum.size());
//    here we have specified the xpath till the row elements, without creating a table element first



    public HerokuAppWebTable(){}


    public void actionTable(){


        System.out.println("Entire text of the table is as below");

        String tableText = tblBody.getText();
//        System.out.println(tableText);

        List <WebElement> rows = tblBody.findElements(By.tagName("tr"));

        System.out.println("Number of rows in table = " + rows.size());

//        List <WebElement> cols = tblHeader.findElements(By.tagName("th"));

//        System.out.println("Number of columns in the table =" + cols.size());

//        findElements method returns WebElement of the type List, hence, we have to always declare List<WebElement> when using the findElements method.


        int rowCount = rows.size();


//        looping table data row by row

        for (int i = 0; i < rowCount; i++) {

//            locating all the columns of this row

//            we are not writing this step to get the count of columns [although that will be needed] but more so to get the child <td>
//            element present under the partent <tr> element of the row
//            this <td> element is the one that contains the data for that column [under the row that we are looping for]
//            so, we dont need to find the count of headers at the start, we are doing that coincidentally at this step
            List<WebElement> colRow = rows.get(i).findElements(By.tagName("td"));
            int colCount = colRow.size();

//            looping to get data for all the columns in this row

            for (int j = 0; j < colCount; j++) {

                String cellText = colRow.get(j).getText();

                System.out.println("cell text = " + cellText);

            }   //col loop

        }   //row loop

//        if we know the cell from which we want to capture the data, we can write something like below

//        getting data for the 3rd row and 2nd column - remember the index starts with 0!
        List<WebElement> dataRow = rows.get(2).findElements(By.tagName("td"));
        String cellValue = dataRow.get(1).getText();

//        and if we want to click on the link in the 6th col

        dataRow.get(5).click();


        }   //end of method


    }   //end of class


Run Selenium tests on IE and Chrome browsers

Download the driver EXEs from www.seleniumhq.org, for the OS version you have. Since firefox driver is bundled in the selenium jar, we do not need to download the firefox driver separately, however, we do have to configure it, just like the other drivers.

Create a folder called 'drivers' under the 'resources' folder, in your project structure

Extract and copy the 'IEDriverServer.exe' and 'ChromeDriver.exe' files in the 'drivers' folder.




This below code demonstrates how you can choose the browser that you want to run your tests in - all you have to do is pass the name of the browser as an input to the Driver method.


import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.firefox.FirefoxDriver;
import org.openqa.selenium.firefox.FirefoxProfile;
import org.openqa.selenium.firefox.internal.ProfilesIni;
import org.openqa.selenium.ie.InternetExplorerDriver;

public class Drivers {


    private WebDriver driver;

    String ieDriverPath = "src\\resources\\drivers\\IEDriverServer.exe";
    String chromeDriverPath = "src\\resources\\drivers\\ChromeDriver.exe";

    public Drivers(String browser){

        setDriver(browser);
    }

    public WebDriver getDriver(){

        return driver;
    }

    public void setDriver(String browser){


        String downloadFolderPath = "C:\\z_All_Downloads\\Java";


        this.driver = null;



        if (browser.equalsIgnoreCase("IE")){

            System.setProperty("webdriver.ie.driver", ieDriverPath);

            InternetExplorerDriver ieDriver = new InternetExplorerDriver();
            this.driver = ieDriver;
        }

        if (browser.equalsIgnoreCase("CHROME")){


            System.setProperty("webdriver.chrome.driver", chromeDriverPath);

            ChromeDriver chromeDriver = new ChromeDriver();
            this.driver = chromeDriver;
        }

if (browser.equalsIgnoreCase("FIREFOX")) {


//creating an object for the profiles

            ProfilesIni allProfiles = new ProfilesIni();

//getting the firefox profile for webdriver, which was created manually

            FirefoxProfile profile = allProfiles.getProfile("webdriverprofile");

//Setting the firefox preferences

// Setting the preferences for download -
            profile.setPreference("browser.download.folderList", 2);
            profile.setPreference("browser.download.dir", downloadFolderPath);
            profile.setPreference("browser.helperApps.neverAsk.saveToDisk", "application/pdf");

//Prevent Firefox from previewing PDFs -

            profile.setPreference("pdfjs.disabled", true);

//Disabling the third party PDF viewers -

            profile.setPreference("plugin.scan.plid.all", false);
            profile.setPreference("plugin.scan.Acrobat", "90.0");
            profile.setPreference("plugin.disable_full_page_plugin_for_types", "application/pdf");

//instantiating the firefox browser with this new profile and preference

            WebDriver firefoxDriver = new FirefoxDriver(profile);

            this.driver = firefoxDriver;

        }


    }


}   //end of class

Common issues and troubleshooting -

  • Error - [The driver executable does not exist: C:\BDD\BDD\src\resources\data\drivers\ChromeDriver.exe]. This generally happens when the driver exe is not located at the referred location, and can be resolved by putting the exe at the correct location

17.6.15

Notes on Array ArrayList HashMap in Java



ArrayArrayList
  • Stores primitive data types and objects, both
  • Stores only objects. This is not to say that we cannot work with primitive data types in ArrayList. Autoboxing feature of java helps us circumvent this.
  • Eg., this works:
  • ArrayList<Integer> integerList = new ArrayList<Integer>();
  • Here we are not storing primitive in ArrayList, instead autoboxing will convert int primitive to Integer object
  • Defined in Java as a fundamental data structure itself
  • Belongs to Collections framework
  • Array is a fixed length data structure. [Static nature]
  • Fixed size - the size of the array has to be defined while declaring the array
  • In an array of size 10 you can set to null your element at index 5. Your array will still have 10 elements numbered 0 to 9 but with an empty element at index 5.
  • ArrayList is a variable length Collection class.
  • Automatically shrinks/grows, as and when elements are removed/added. [This is its Dynamic nature]. We can create instance of ArrayList without specifying size
  • Stores similar data of one type
  • Can store heterogeneous data types
  • Cannot use Generics with Array, because Array instance must know about what kind of data type it can hold, and throws ArrayStoreException, if you try to store a type which is not convertible into type of Array
  • Can use Generics with Array
  • No of elements = Array.length
  • No of elements = ArrayList.size()
  • You can simply use assignment operator to store element into Array
  • objArray[1] = new Object();
  • You have to use add() method to insert element into ArrayList.
  • It is not a class
  • It is a class with many methods
  • Cannot be synchronized, so cannot be used in multithreaded env
  • Can be obtained a synchronized version
  • Elements retrieved with For loop
  • Can be retrieved with For loop and iterators
  • Elements accessible with index number
  • Accessing methods like get() etc. are available
  • Can be multidimensional
  •  
  
  
  
ArrayListHashMap
  • ArrayList implements List Interface
  • HashMap is an implementation of Map interface
  • ArrayList maintains the insertion order
  • HashMap doesn’t maintain any order, the returned key-values pairs are not sorted in any kind of order
  • ArrayList allows duplicate elements
  • HashMap doesn’t allow duplicate keys (It does allow duplicate values)
  •  
  • If you want an array of all the keys in the hash map, you can use the keySet() method










14.6.15

Miscellaneous Code, Tips and Tricks on QTP

Reusing Objects after Page Refreshes via Init

QTP web test objects go out of sync whenever the webpage Refreshes/Reloads. This means that if you held a reference to a web-object, you couldn’t could on it to work throughout your script.

'By using a .Init command after the page loads, the web-object resyncs, and the script will not break.

''Set oBrowser = Browser("version:=inter.*")
oBrowser.Navigate ""http://www.google.com"
Set oWebEdit = oBrowser.WebEdit("name:=q", "index:=0")
oWebEdit.Set "software inquisition"
oWebEdit.submit ''Page reloads
oBrowser.sync

'This resyncs oWebEdit
oWebEdit.init

'Now the next line will work
oWebEdit.Set "Bonnaroo"

--------------------------------------------------

Changing Time-out Options on Remote Machine [RDC]

[HKEY_CURRENT_USER\Software\Policies\Microsoft\Windows\Control Panel\Desktop]
"ScreenSaverIsSecure"="0"
"ScreenSaveActive"="0"
"ScreenSaveTimeOut"="999999999"

--------------------------------------------------

Quick way to generate Unique Temporary files at Runtime

Many a times we need to create all sorts of temporary files with unique names; and after the test is over they are not useful anymore. But to do this we usually ending up writing a large code for creating a new folder, then doing a lots of checks, and then finally creating a file, and then using the FilePath where ever it is that we wanted!
A quicker way of doing this and avoiding all the creation and checks for new folders is by using the Current Report Path of the test during Runtime itself, and using the DotNETFactory utility

sFilePath = Reporter.ReportPath & "\" & DotNETFactory.CreateInstance("System.DateTime").Now.ToString("ddMMyyHHMMss") & ".png"

--------------------------------------------------

Variations of SendKeys Method

This code works and has been verified!
'Create DeviceReplay object
Set objSendKey = CreateObject("Mercury.DeviceReplay")

'Focusing on the Object by clicking it
Browser("Google").Page("Google").WebElement("WebElement").Click

'Call the required function
objSendKey.SendString("Hi, Your text goes here!!!")

'Release the object
Set objSendKey = Nothing

--------------------------------------------------

How to Clear or Delete text from Edit Box

When the Set method is used, it first clears the text in the EditBox and then writes new text in the EditBox
This may also be possible by the following code:
Browser("B").Page("P").WebEdit("E").Object.Clear
What should we do if we have to just Type next to next and not overwrite the text already present

--------------------------------------------------

Keyboard Status

The Devices.Keyboard class Provides properties for accessing the current state of the keyboard, such as what keys are currently pressed, and provides a method to send keystrokes to the active window.
How can we know if CAPS-LOCK already pressed?
Before we use the numpad keys we want to verify that if NUM-LOCK already pressed.

Set Keyboard = DotNetFactory.CreateInstance( "Microsoft.VisualBasic.Devices.Keyboard", "Microsoft.VisualBasic" )

Print CBool( Keyboard.AltKeyDown )
Print CBool( Keyboard.CapsLock )
Print CBool( Keyboard.CtrlKeyDown )
Print CBool( Keyboard.NumLock )
Print CBool( Keyboard.ScrollLock )
Print CBool( Keyboard.ShiftKeyDown )
Source: http://www.advancedqtp.com/2008/04/keyboard-status/

--------------------------------------------------

Explanation of a Click

Click is not a physical click, but its just a 'Return' Event, which is why even when we see that the button has been clicked, the button would not have been actually clicked, because qtp would have sent a Return which did not get registered.
So, we may be able to correct this by changing the Replay Type

--------------------------------------------------

Use OLE Objects to get number of pages in PDF

Function GetNumPagesInPDF(FileName)
    Dim oPDFDoc
    Set oPDFDoc = CreateObject( "AcroExch.PDDoc" )

    If oPDFDoc.Open( FileName ) Then
        GetNumPagesInPDF = oPDFDoc.GetNumPages()
        Set oPDFDoc = Nothing
    Else
        GetNumPagesInPDF = -1
    End If
End Function

numPages = GetNumPagesInPDF("C:\Program Files\Mercury\QuickTest Professional\help\QTUsersGuide.pdf")
MsgBox "Number of pages: " & numPages

--------------------------------------------------

Difference between Class Name, micClass, micclass, className

Class Name: When looking through the object spy on any object, we'll see the test-object property "Class Name", which always equals to the QTP-Type of that object. So for example, the Class Name of a browser is "Browser", the Class Name of a WinButton is "WinButton".

However, if you wish to use the "Class Name" property to identify objects with Descriptive Programming syntax, you'd have to use the property micclass.

So for example, this won't work:
Browser("Class Name:=Browser")
But this will:
Browser("micclass:=Browser")"

So, this takes case of Class Name and micclass, what about the plain old Class and className properties? These properties are usually unique to Web objects.
className is a Run-Time object property of Web objects. You can test it yourself: build a symple HTML file, and add class="Something" to one of the HTML nodes. When you'll load that HTML file in a browser, and use the object spy on the relevant web-object, you'll see className="Something" in the Run-Time tab of the object spy.
class is simply the Test-Object property which equals the Run-Time property of className. Meaning that oWebObject.GetROProperty("class") will be the same as oWebObject.Object.className. They represent the same inner data, once through the Run-Time world, and once through the Test-Object world.

--------------------------------------------------
Change the default directory for Tests path for QTP

Open the registry editor (Start -> Run -> type ""regedit"".)

Navigate to the following key:
HKEY_LOCAL_MACHINE\SOFTWARE\Mercury Interactive\QuickTest Professional\MicTest

Find the TestsDirectory value. The value contains the path to the directory you want to be the default test script directory. Edit this value to have your desired path
Right click on TestsDirectory
Choose Modify from the menu
Enter the path into the Value data field
Click OK
Repeat steps 2 through 4 for the following key:
HKEY_CURRENT_USER\Software\Mercury Interactive\QuickTest Professional\MicTest

If the specified directory path does not exist, QuickTest Professional will open the "My Documents" directory by default.

You should not place a "\" at the end of the path.

--------------------------------------------------

Get Content from WinList Form

Window("Window").Activate
text= Window("Window").WinList("From").GetContent

12.6.15

Apache POI vs JXL

Comparison of POI and JXL libraries to work with Excel for data driving tests in Selenium and Java


Apache POI JXL
 Is actively maintained Not under active dev and maintenance, last update was in 2012
does not support new xml format like XLSX
seems simpler to use
Apache poi does not seem to have a direct method to get the content of a particular cell via the parent "sheet" object
And above that we have to define the method of capture based on the data type for each cell like string, numeric, boolean, etc
And then for a numeric value, it would return a value of 1.0 even if the cell just had "1"
But I have overcome this limitation by converting the cell data into string before actually passing it on as a value. So this is not an issue any more.
Apache POI does not have any method to get a count of all the columns present in an excel; JXL has such a method. This would have been really useful when reading data from excel for parameterization
JXL does not support the Excel 2007+ ".XLSX" format; it only supports the old BIFF (binary) ".xls" format. Apache POI supports both with a common design.
Additionally, the Java portion of the JXL API was last updated in 2009 (3 years, 4 months ago as I write this), although it looks like there is a C# API. Apache POI is actively maintained.
JXL doesn't support Conditional Formatting, Apache POI does, although this is not that significant, because you can conditionally format cells with your own code.
JXL doesn't support rich text formatting, i.e. different formatting within a text string; Apache POI does support it.
JXL only supports certain text rotations: horizontal/vertical, +/- 45 degrees, and stacked; Apache POI supports any integer number of degrees plus stacked.
JXL doesn't support drawing shapes; Apache POI does.
JXL supports most Page Setup settings such as Landscape/Portrait, Margins, Paper size, and Zoom. Apache POI supports all of that plus Repeating Rows and Columns.
JXL doesn't support Split Panes; Apache POI does.
JXL doesn't support Chart creation or manipulation; that support isn't there yet in Apache POI, but an API is slowly starting to form.

Apache POI has a more extensive set of documentation and examples available than JXL.

there is j-excel which supports xlsx but its proprietary








Recording Modes in LoadRunner

Comparison of different Recording Modes in LoadRunner




No   HTML Mode URL Mode GUI Mode
1 Mode of Recording HTML Mode is the Default mode of recording in LR for Web(HTTP/HTML) Protocol The URL-mode option instructs VuGen to record all requests and resources from the server. This is introduced with Web (Click & Script) protocol. 
2   Each USER ACTION is recorded as a separate request.  This is also called as Context based recording It automatically records every HTTP resource as separate URL steps (Request). This recording mode captures even non-HTML applications such as applets and non-browser applications. The GUI-mode option instructs VuGen to record all editable fields in an object or non-browser applications.
    This means everything you do on the web page will be recorded in a single function When a web site is launched apart from the HTML content, there will be images, java script files, CSS files an other resources downloaded. Each of these resources is recorded as a separate request. This is similar to functional testing when objects are detected at the GUI-level
    We would be able to recognize each “logical” requests/call made to the server, making amendments to the script easily. This mode does not depend on the UI of the application, rather the actions associated with the user actions performed on UI  
      This works good with non-HTML applications such as applets and non-browser applications (e.g. Win32 executables).  
3 Intuitiveness Scripts are more intuitive to understand and easy to modify Difficult to work and modify Scripts are in the form of GUI Objects
4 Advantages The advantages of using the HTML recording mode is that the size is very compact and the customization efforts are reduced The benefit of having scripts with URL recording mode is that the maintenance cost associated with these are reduced and can be used across various releases of the product making the script less susceptible to changes in the UI  
5 Disadvantages However, with UI changes to the web applications the scripts would require much higher maintenance costs As each resource is recorded the size of the script is large.  This means that a large amount of customization is also required.  
6 Explicit URLs only Another option is available under “Advanced options” of HTML mode  is Explicit URLs only mode. NA NA
    The benefits of the HTML mode and URL mode are cobbled together in HTML  -  Explicit URLs only.    
    With this mode, the size of the script is compact (as only the user action are recorded as requests, not at the UI level but at the request level).    
    This requires more customization effort, but has the advantage of high maintainability for longer durations    
    This is generally the most commonly used and recommended recording method for web applications where the scripts have to be maintained for longer durations