Most Viewed Pages

4.12.14

Create a BDD project via JBehave Archetype


The fastest way to start building and automating BDD Stories via JBehave tool is to have the entire Framework/Project structure created via Maven Archetypes using the jbehave-simple-archetype.

This generates a project structure with all the necessary config and guidelines which help in implementing the Story files right away, and saves us a lot of time in writing a lot of boiler-plate-code.

Just navigate to the dir [lets say, C:\BDD\] where you want to keep all your BDD projects, and then enter the below in the cmd prompt to download the project via mvn

mvn archetype:generate -DarchetypeGroupId=org.jbehave -DarchetypeArtifactId=jbehave-simple-archetype -DarchetypeVersion=4.6.3 -DarchetypeRepository=https://nexus.codehaus.org/content/repositories/releases/org/jbehave/jbehave-simple-archetype/


Project Specification - 
  • When asked to enter a groupID, enter like: com.company.department
  • When asked to enter an atifactID, enter like: bdd-jbehave
  • When you are asked to define value for version just press enter to select the default version as 1.0-SNAPSHOT
  • Let the default package be same as groupId so press Enter and confirm the details by typing “y” and then enter as seen below.
  • After successful completion you will see a folder named after your artifactId in your workspace which contains a pom.xml and also src folder.
  • This would also contain a sample MyStories.java and MySteps.java files, with default config

We get the following major classes/files
  • MyStories.java - contains all config to run JBehave stories
  • MySteps.java - contains implementation of all steps
  • my.story - contains all the scenarios for a story
  • pom.xml with all the dependencies and build config





That's it, your maven project is created. You can use this as a template to add your own story, steps and other classes.


To open the project in IntelliJ - 
Select the option to import a new project from the IDE, and then specify the pom.xml for the newly created jbehave project.
On the subsequent windows, select the option to automatically download the Source and Documentation. This will automatically download all the packages that you import in your classes, as and when they are used, and will prevent package not found errors.
Ensure that the JBehave plugin is installed in IntelliJ, before importing the project.
Ensure that you select the 'Sources' and 'Documentation' checkboxes while importing, so that all the dependencies get downloaded.



[Optional step] To open the project in Eclipse - 
Now cd into the folder jbehave which contains the pom.xml and then execute the following command:
    mvn eclipse:eclipse
This command will make your project an eclipse project which can be opened through eclipse by adding the relevant .classpath and .project files.

That's it, you are ready to do BDD, just behave!

Steps to install and configure Maven

Steps to install Maven

Prerequisite - Ensure that Java is installed, and the environment variable 'JAVA_HOME' is set as follows:
JAVA_HOME=C:\Program Files\Java\jdk1.7.0_10

Download and unzip the maven binary file into a location like 'C:\Program Files\Apache\maven'. There is no exe to run.

Set the environment variables. Open the cmd prompt and type in the below commands as is

set M2_HOME=C:\Custom_Install_Dir\Apache\maven
set MAVEN_HOME=C:\Custom_Install_Dir\Apache\maven

Then append this to the Path variable as below, so that we can run the maven commands from anywhere
set Path=C:\Apache\maven\apache-maven-3.6.1\bin;

You can also do this by directly editing the Environment Variables, if you have admin rights.

How to check if maven has been installed correctly?

If we get an output like below to the command 'mvn -version', then we are all set

That's it, maven is installed and configured!



Some DONTs -
  • No need to set up MAVEN_OPTS Env param anymore.
    • All the options can now be set via the JVM Config file - to be added as - ${maven.projectBasedir}/.mvn/jvm.config 
    • This file will become part of your project and will be checked in along with your project.
    • Also this is way easier than having to get admin rights in enterprise setups.
  • Dont place your maven in a dir having spaces in its path.

Common Troubleshooting -
  •  If you are still having issues, even after following the above steps correctly, first restart the machine before doing any more troubleshooting
  • If 'mvn' command does not work directly, give the entire path till the bin dir of maven, and then try - if this works, then it means maven is installed and recognized, but it cannot run from everywhere. So all you need to fix are the Environment Variables.
  • By default Eclipse points to its own Embedded version of Maven and this could be different from the one that you installed, so we should update Eclipse to use the same Maven package and version via Eclipse > Preferences
  • Ensure that the Path variable has both these values - C:\Program Files\Java\jdk1.8.0_211\bin;C:\Apache\maven\apache-maven-3.6.1\bin;

2.12.14

Function to delete firefox cookies with VbScript / QTP

There is a QTP Util method to delete browser cookies, but that works only for IE.
Deleting the cookies for firefox programatically is a little tricky, specially if there are multiple profiles that you are using, but here is a function to do just that.

Function funcDeleteCookies()

''Ignoring any errors that may arise during file deletion

On Error Resume Next

''This function will work best when firefox is closed

Call funcTerminateProcess("firefox.exe")

''Defining the list of files that need to be deleted to clear the cache

'' arrFileToDel = Array("compatibility.ini","cookies.sqlite","cookies.sqlite-shm","cookies.sqlite-wal","extensions.ini","extensions.sqlite","formhistory.sqlite","key3.db","localstore.rdf","permissions.sqlite","places.sqlite","places.sqlite-shm","places.sqlite-wal","prefs.js","sessionstore.bak","sessionstore.js","urlclassifierkey3.txt","webappsstore.sqlite")

arrFileToDel = Array("cookies.sqlite","cookies.sqlite-shm","cookies.sqlite-wal","formhistory.sqlite","places.sqlite","places.sqlite-shm","places.sqlite-wal","sessionstore.bak","sessionstore.js","localstore.rdf","formhistory.sqlite","key3.db")


''Getting the current logged in user, because the path is user specific

sUserName = Environment("UserName")

''Location of the firefox profile folder

sProfileFolderFox = "C:\Users\" & sUserName & "\AppData\Roaming\Mozilla\Firefox\Profiles"

Set oFolderFSO = CreateObject("Scripting.FileSystemObject")


If Not oFolderFSO.FolderExists(sProfileFolderFox) Then


Call funcLogger(micWarning, "The firefox cache folder could not be located", "Cache not cleared. " & sProfileFolderFox)


Else


''Getting all the sub folders

Set oChildFolders = oFolderFSO.GetFolder(sProfileFolderFox).SubFolders

''Looping for each of the sub folders

For Each oFolder In oChildFolders

sCurrFolderName = oFolder.Name


''Generally its enough to clear the cache from the default folder, which is what we are checking below

If InStr(1,LCase(sCurrFolderName),".default",1) Then

''Deleting the files

For i = 0 To UBound(arrFileToDel) - 1
oFolderFSO.DeleteFile(sProfileFolderFox & "\" & sCurrFolderName & "\" & arrFileToDel(i))
Next

End If


Next


End If


''Enabling errors again

On Error GoTo 0

End Function

19.11.14

Connect to database via JDBC

Though we have numerous methods [and sophisticated too] to connect to a database with java, if you are looking for a simple snippet to just connect, run a query, and get the result, this below code will suffice.
Also, if your purpose is just to query and get results, just having the right jar would be enough, no need for the database client/driver installation.

--------------------------------------
//function to connect to database using JDBC/JConnect
public Connection getJDBCConnection(){

System.out.println("Getting DB Connection properties");
Properties properties = getPropertyValues("test1.properties");

String dbDriver = properties.getProperty("database.driver");
String dbServer = properties.getProperty("database.server");
String dbServerPort = properties.getProperty("database.port");
String dbName = properties.getProperty("database.name");
String dbUsername = properties.getProperty("database.username");
String dbPassword = properties.getProperty("database.password");

String dbURL = "jdbc:sybase:Tds:" + dbServer + ":" + dbServerPort + "/" + dbName;

//Initializing the connection object
Connection connection= null;

try{
//Register the database driver
Class.forName(dbDriver);

//Open a connection
System.out.println("Connecting to database - " + dbURL);
connection = DriverManager.getConnection(dbURL, dbUsername, dbPassword);
System.out.println("DB connection successful");

}catch(SQLException se){
se.printStackTrace();
}catch(Exception e){
e.printStackTrace();
}

return connection;
}
--------------------------------------

//function to run query and get the resultset back
public ResultSet runDBQuery(Connection connection, String sqlToRun){

Statement statement = null;
ResultSet resultSet = null;

try{

statement = connection.createStatement();

System.out.println("Executing SQL Query - " + sqlToRun);
resultSet = statement.executeQuery(sqlToRun);

}catch(SQLException se){
se.printStackTrace();
}catch(Exception e){
e.printStackTrace();
}finally{
try{
if(connection.isClosed() == false)
connection.close();
}catch(SQLException se){
se.printStackTrace();
}//end finally try
}//end try

return resultSet;
}
--------------------------------------

Now to use all of these...
--------------------------------------
String sqlToRun = "SELECT EmployeeID FROM Employee Where EmployeeID = 245145";
try{
ResultSet rs = commonLib.runDBQuery(commonLib.getJDBCConnection(),sqlToRun);

while(rs.next()){
//Retrieve by column name
int id = rs.getInt("EmployeeID");
//String last = rs.getString("last");

System.out.println("EmployeeID: " + id);
}
rs.close();
}
catch(SQLException se){
//Handle errors for JDBC
se.printStackTrace();
}catch(Exception e){
//Handle errors for Class.forName
e.printStackTrace();
}
--------------------------------------
Output will be...
EmployeeID: 245145


The jdbc properties are as follows:

#This is the standard driver class for connecting to Sybase database using JConnect jar
database.driver=com.sybase.jdbc4.jdbc.SybDriver
database.server=abc.xyz.net
database.port=5500
database.name=emp_comp
database.username=autobot
database.password=autobot1

Read properties file in Java

Function to get all the properties from a given file, and return the properties object

//The properties files are all supposed be placed under this folder - "C:\\Automation\\resources\\", hence, only the filename is passed along
public Properties getPropertyValues(String propFileName){

String propFilePath = "C:\\Automation\\resources\\" + propFileName;
System.out.println("Reading properties from - " + propFilePath);

//initializing the objects
Properties properties = new Properties();
InputStream inputStream = null;

try {

inputStream = new FileInputStream(propFilePath);

// load a properties file
properties.load(inputStream);

}catch (FileNotFoundException f) {
f.printStackTrace();
} catch (IOException ex) {
ex.printStackTrace();
} finally {
if (inputStream != null) {
try {
inputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}

//This will return the properties object which can then be used to get all the properties from a give file.
return properties;
}

Export all the Environment Variables to a file

Steps to Export all your Environment Variables to a file. This will be helpful in corporate environments, where we dont have admin rights to browse/update Environment variables

1. Open cmd prompt.
2. Type in C:> set >> allenvvar.txt

The file will be created in the C drive

Voila!

BAT to launch applications with specific Environment Variables

Often you end up in situations, where after installing some software, your previous ones stop working; or the new ones dont work as they should as previous ones are interfering. One of the reasons for this issue could be the environment variables being set and used by such software. And this always happens when you have QTP [along with java add-in] installed, which causes other java-based software to just not launch/start altogether.
To overcome this issue of same environment variables being used by different programs, we can create a .BAT file to temporarily set and launch/start the applications with those environment variables.

This below code will help launch DBArtisan [database client] by setting up the environment variables required for it, some of which have been hijacked by QTP.
We can write similar stuff for any application we want.

-----------------------------------------------
Set SYBASE=C:\Progra~2\Syb155

Set SYBASE_OCS=OCS-15_0

Set INCLUDE=C:\Progra~2\Syb155\OCS-15_0\include;%INCLUDE%

Set LIB=C:\Progra~2\Syb155\OCS-15_0\lib;%LIB%

Set PATH=C:\Progra~2\Syb155\OCS-15_0\bin;C:\Progra~2\Syb155\OCS-15_0\dll;C:\Progra~2\Syb155\OCS-15_0\lib3p;%PATH%

Set PATH=C:\Progra~2\Syb155\DataAccess\OLEDB\dll;%PATH%

Set PATH=C:\Progra~2\Syb155\DataAccess\ODBC\dll;%PATH%

Set LIB=C:\Progra~2\Syb155\DataAccess\ADONET\dll;%LIB%

Set PATH=C:\Progra~2\Syb155\DataAccess\ADONET\dll;%PATH%


Start C:\Progra~2\Enbarcadero\dbart901_11364_ion.exe

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

3.11.14

Wait and Sync in Selenium

There are broadly 3 different options to choose from...



Implicit Wait - 
  • An implicit wait is to tell WebDriver to poll the DOM for a certain amount of time when trying to find an element or elements if they are not immediately available. The default setting is 0. Once set, the implicit wait is set for the life of the WebDriver object instance, ie., as long as the browser is opened, all the elements will take the amount of time set as implicit wait to load.
  • Implicit wait is defined at the browser level, and not at an individual element level, hence, Implicit waits will be useful only when entire page loads. (i.e., It won't wait for dynamically loading ajax elements). The implicit wait only waits for an element to appear in the DOM, so it returns immediately, but when you try to interact with the element you get a NoSuchElementException.
  • There can be instances when a particular element takes more than a minute to load. In such a case if we set a huge time for Implicit wait, then the browser may wait for that amount of time for every element. To avoid that situation you can simply put a separate time on the required element only. By following this your browser implicit wait time would be short for every element and it would be large for specific element- and this can be achieved via Explicit Wait.

Syntax -
driver.manage.timeouts().implicitlyWait(10,TimeUnit.SECONDS);



WebDriverWait \ Explicit Wait - 

  • An explicit wait is a code you define to wait for a certain condition to occur before proceeding further in the code. 
  • Explicit waits are intelligent waits that are confined to a particular web element. Instead of instantly looking for an element, we can tell Webdriver to wait for a certain amount of time before we continue with the next step.
  • The worst case of this is Thread.sleep(), which sets the condition to an exact time period to wait. WebDriverWait in combination with ExpectedCondition is a more preferred mode of implementation.

Syntax -
WebDriverWait wait = new WebDriverWait(driver,10);
wait.until(ExpectedConditons.elementToBeClickable(By.xpath("locator"));



FluentWait -

FluentWait uses a Polling Technique to wait i.e, it will keep on Polling every fixed interval for a particular element. But the important feature with FluentWait is that it uses Generics, which means we dont have to pass an instance of the WebDriver - we can directly use the WebElement, of By, or anything else.

Let’s say you have an element which sometime appears in just 1 second and some time it takes minutes to appear. In that case it is better to use fluent wait, as this will try to find element again and again until it find it or until the final timer runs out.

Advantages of FluentWait over WebDriverWait - 
  • You dont have to pass the driver instance in FluentWait. This can be very helpful if you are using the PageObject Pattern for your Framework.
  • You have more control over the wait time with the polling option - because with WebDriverWait, selenium would wait for the entire duration specified [lets say 20s] but with FluentWait we have the option of specifying the wait as well as the polling interval, hence, the actual wait time can be reduced with 5s wait and 4X polling, instead of directly waiting for 20s.
So its advantageous to use FluentWait for all the sync operations, as it gives fine-tuned control.

This is a function that demonstrates the use of FluentWait, and as you can see, we did not have to pass/use an instance of the WebDriver while creating this function.
------------------------------------------------------------
import org.openqa.selenium.support.ui.FluentWait;

//The FluentWait class uses the Function to implement .until
//This Function uses the following package [com.google.common.base.Function]
//There are many packages available for "Function", but only this has to be used,
// otherwise we get all sorts of weird errors
//Also, in the above function, we must use this class 'org.openqa.selenium.NoSuchElementException' instead of the default [import java.util.NoSuchElementException] suggested by IDE because if we use the java.util, then the FluentWait will fail with NoSuchElementException!! since, we did not use the correct package - stupid ide!
//So we should use the full package name anywhere we have to use the class declaration, otherwise, if we copy the code, and it asks us for the package, it might just add the default one again.

public Boolean checkElementIsDisplayedFluentWait(WebElement webElement) {

System.out.println("running checkElementIsDisplayedFluentWait");

Boolean displayStatus = false;

FluentWait<WebElement> fluentWait = new FluentWait<WebElement>(webElement);
fluentWait.ignoring(NoSuchElementException.class);
fluentWait.withTimeout(10, TimeUnit.SECONDS);
fluentWait.pollingEvery(5, TimeUnit.SECONDS);

displayStatus = fluentWait.until(new Function<WebElement, Boolean>() {
public Boolean apply(WebElement webElement) {
return webElement.isDisplayed();
}
});

System.out.println(displayStatus.booleanValue());

return displayStatus;

}

And it can be used as follows -
This will check if the element is displayed, and then capture its displayed text.
if(commonLib.checkElementIsDisplayedFluentWait(webElement)){
System.out.println(webElement.getText());
}
------------------------------------------------------------


Need to explore the option to check for conditions/properties using the FluentWait like in the WebDriveWait

Also, all of the above examples will work when there is a change in the DOM, but there can be situations where the page sends requests for data without changing the DOM. In such cases, we may opt to check for asynchronous events using JQuery or JScript.

Stay tuned for more, as this is still wip...

16.9.14

Automatically Download Files with Selenium

Selenium itself cannot interact with system-level dialogs opened by JS in the browser. In order to download PDFs as part of the browser automation process, it requires the help from either additional frameworks or an approach that handles the downloads automatically, and prevent Firefox from popping up the "Save file" dialog.

One way is to use the Firefox preferences to download the files directly without going through the dialog box, and here is the code that will do just that.

This approach is better as we don't have to use custom/third party software to deal with the dialog boxes separately, which can become tedious and difficult to integrate with the already existing complex setup we usually have for selenium.


public WebDriver getFireFoxProfileDriverForDownload(){

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

        //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 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
        WebDriver firefoxDriver = new FirefoxDriver(profile);

        //This driver instance can now be used to open firefox with the above preferences
        return firefoxDriver;

    }


Description of the code above -
·        Setting the preferences for download -
The preferences can be set using the setPreference method of the FirefoxProfile class. This method needs the value of the preferences in key-value pairs, where the key is the name of the preference and the value is the option that you want to set it to. The name and acceptable/allowable values for the preferences can be found by browsing the 'config' properties of the firefox, via the 'about:config' page. The key would be the 'Preference Name' and the value would be the 'Value', as seen from the 'config' window of the firefox.
Firefox’s download manager preferences can be set programmatically while instantiating FirefoxDriver. The following properties can be used for this.
  • "browser.download.folderList" - This controls the default folder to download a file to. 0 indicates the Desktop, 1 indicates the systems default downloads location and 2 indicates a custom folder.
  • "browser.download.dir" - This holds the custom destination folder for downloading. It is activated if browser.download.folderList has been set to 2.
  • "browser.helperApps.neverAsk.saveToDisk" - This stores a comma-separated list of MIME types to save to disk without asking what to use to open the file.

The MIME type defined here is "application/pdf", which is a type that most PDF files use. However, if the target PDF file has a non-standard MIME type, then “Save file” dialog might still show up. In order to fix this issue, the actual MIME type has to be added into browser.helperApps.neverAsk.saveToDisk property, which can be checked out using either of the following approaches:
  • Upload file to online tools like - http://mime.ritey.com/
  • Download file and monitor MIME type in Chrome’s developer tool or web debugging proxy like Fiddler, CharlesProxy, etc.
·        Prevent Firefox from previewing PDFs -
With the release of Firefox 19.0, PDF.js has been integrated into Firefox to provide built-in ability of displaying PDF files inside browser. It tries to parse and render PDFs into HTML5, which can be automated using Selenium WebDriver in theory. However, to download PDFs instead of preview in Firefox, another about:config entry needs to be changed to disable PDF.js.

·        Disabling the third party PDF viewers -
Except for Firefox’s built-in PDF viewer, there might be other third party plugins preventing Firefox from downloading PDFs automatically. If a machine has Adobe Reader installed, then default PDF viewing setting in Firefox might have been set to Adobe Acrobat without notice.
To avoid previewing PDFs with those plugins, two more about:config entries need to be configured when starting WebDriver instance.
  • "plugin.scan.plid.all" - This needs to be set to false, so that Firefox won’t scan and load plugins.
  • "plugin.scan.Acrobat" - This is a key that holds the minimum allowed version number that Adobe Acrobat is allowed to launch. Setting it to a number larger than currently installed Adobe Acrobat version should do the trick.
  • "plugin.disable_full_page_plugin_for_types" = "application/pdf" - Without this, the pdf gets opened in the browser itself, instead of getting downloaded.