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    

BAT file to Register a DLL


If you have a number of DLLs that you want to register, then considering creating a BAT script for that.

Create a file with .bat extension, and enter the one line command, like below, for each dll.

regsvr32 "C:\Program Files\DLLNameToRegister.dll"


Its not necessary but advisable to have the entire path of the DLL mentioned in the above command, which will save anyone the trouble of fixing 'dll not found' issues. One of the other ways you can do this is by saving the .bat file in the same dir as the DLL, but this may not be always possible.

Also, you may need Admin rights to register some DLLs, so make sure you run the .bat file with an admin ID.
Once done, you will get a message that says that the registration succeeded.