"No one is harder on a talented person than the person themselves" - Linda Wilkinson ; "Trust your guts and don't follow the herd" ; "Validate direction not destination" ;

October 27, 2011

Automation Assignment - Selenium, TestNG - Improvements Post

[Previous post in this series - Automation Assignment - Selenium, TestNG]

Based on previous post. I got couple of comments on improvements for this code. The enhancements done are
  • Soft Assertions
  • Removing Thread Sleep code. WaitForCondition is used instead of it
  • Configuring Page Load using a common timeout value
From Selenium documentation found difference between assert and verify
  • If you use an assert, the test will stop at that point and not run any subsequent checks.
  • In contrast, verify commands will not terminate the test
Handling Soft Assertions is done based on Selenium Example post. Modified HomePageTest.java as below. You can download files for Soft-Assertions and add it to the project. As you can see below HomePage extends TestBase class present in Soft Assertions.

import java.io.File;
import java.io.FileOutputStream;
import org.testng.annotations.*;
import com.thoughtworks.selenium.DefaultSelenium;
import com.thoughtworks.selenium.Selenium;

public class HomePageTest extends TestBase {
      Selenium selenium;
                        public static final String WAITFORPAGELOADTIME = "30000";
                       
      @Parameters( { "browserpath", "appurl"})
      @BeforeTest(alwaysRun = true)
      public void init(String browserpath, String appurl) {
            selenium = new DefaultSelenium("localhost", 4444, browserpath, appurl);
            selenium.start();
            selenium.deleteAllVisibleCookies();
            selenium.refresh();
      }

      @AfterTest
      public void tearDown() {
            selenium.stop();
      }
     
      /* Test for 1 way flight  */
      @Test(dataProvider = "dataProviderSearchFlightsOneWay")
      public void SearchFlightsOneWay(String from, String to) {
            try {
                  selenium.open("/");
                  selenium.type("//input[@id='origin_autocomplete']", from);
                  selenium.type("//input[@id='destination_autocomplete']", to);
                  selenium.click("//img[@alt='Calendar']");
                  selenium.click("link=20");
                  selenium.click("button_flight_search");
                  selenium.waitForPageToLoad(WAITFORPAGELOADTIME);
                  verifyResults("1");
            } catch (Exception e) {
                  System.out.println("Exception Occurred " + e.toString());
            }

      }

      /* Test for round trip flight  */
      @Test
      public void SearchFlightsRoundTrip() {
            try {
                  selenium.open("/");
                  selenium.type("//input[@id='origin_autocomplete']", "MAA");
                  selenium.type("//input[@id='destination_autocomplete']", "BLR");
                  selenium.click("//img[@alt='Calendar']");
                  selenium.click("link=17");
                  selenium.click("id=rnd_trip");
                  selenium.click("//*[@id='rtn_date']");
                  selenium.click("link=30");
                  selenium.click("button_flight_search");
                  selenium.waitForPageToLoad(WAITFORPAGELOADTIME);
                  verifyResults("2");
            } catch (Exception e) {
                  System.out.println("Exception Occurred " + e.toString());
            }
      }

      /* verifier for search results  */
      public void verifyResults(String Filter) {
            selenium.waitForCondition("selenium.isElementPresent(\"//*[@id='mod_link']\");",
            WAITFORPAGELOADTIME);
            verifyTrue(selenium.isElementPresent("mod_link"));
            verifyTrue(selenium.isElementPresent("facebookLink"));
      }

      /* Test for train search  */
      @Test
      public void testTrainSearch() {
            try {
                  selenium.open("/");
                  selenium.click("link=Trains");
                  selenium.waitForPageToLoad(WAITFORPAGELOADTIME);
                  selenium.type("from_station", "chennai");
                  selenium.keyPressNative(java.awt.event.KeyEvent.VK_TAB + "");
                  selenium.type("to_station", "bangalore");
                  selenium.keyPressNative(java.awt.event.KeyEvent.VK_TAB + "");
                  selenium.select("trainClass", "label=AC 2 Tier (2A)");
                  selenium.click("css=img[alt=\"Calendar\"]");
                  selenium.click("//a[contains(text(),'17')]");
                  selenium.keyPressNative(java.awt.event.KeyEvent.VK_TAB + "");
                  selenium.click("//button[@type='submit']");
                  selenium.waitForCondition(
                              "selenium.isElementPresent('id=mod_link')", "60000");
            } catch (Exception e) {
                  System.out.println("Exception Occurred " + e.toString());
            }

      }

      /* Test for Hotels Search  */
      @Test
      public void searchHotels() {
            try {

                  selenium.open("/");
                  selenium.click("link=Hotels");
                  selenium.waitForPageToLoad(WAITFORPAGELOADTIME);
                  selenium.type("city", "chennai");
                  selenium.click("//img[@alt='Calendar']");
                  selenium.click("link=12");
                  selenium.keyPressNative(java.awt.event.KeyEvent.VK_TAB + "");
                  selenium.click("//img[@alt='Calendar']");
                  selenium.click("link=29");
                  selenium.click("//button[@type='submit']");
                  selenium.waitForPageToLoad(WAITFORPAGELOADTIME);
                  selenium.waitForCondition(
                              "selenium.isElementPresent('id=mod_link')", "60000");
            } catch (Exception e) {
                  System.out.println("Exception Occurred " + e.toString());
            }
      }

      /* Test to verify headers  */
      @Test
      public void verifyHeaders() {
            try {
                  selenium.open("/");
                  verifyTrue(selenium.isElementPresent("link=Hotels"));
                  verifyTrue(selenium.isTextPresent("Hotels"));
                  verifyEquals("Trains", selenium.getText("link=Trains"));
                  verifyTrue(selenium.isElementPresent("link=Trains"));
                  verifyEquals("Small World", selenium
                              .getText("link=Small World"));
                  verifyTrue(selenium.isElementPresent("link=Small World")); 
                  verifyEquals("more", selenium.getText("link=more"));
                  verifyTrue(selenium.isElementPresent("link=more"));
                  verifyTrue(selenium.isElementPresent("link=My Trips"));
                  verifyTrue(selenium.isElementPresent("link=Sign in"));
                  verifyTrue(selenium.isElementPresent("link=Register"));
                  verifyTrue(selenium.isElementPresent("link=Register"));
                  verifyTrue(selenium
                              .isElementPresent("//ul[@id='global']/li[5]/a/strong"));
                  verifyEquals("Tell us what you think", selenium
                              .getText("//ul[@id='global']/li[5]/a/strong"));
                  verifyTrue(selenium
                              .isElementPresent("//ul[@id='global']/li[5]/a/strong"));
            } catch (Exception e) {
                  System.out.println("Exception Occurred " + e.toString());
            }

      }

      /* Test to verify footers  */
      @Test
      public void verifyFooter() {
            try {
                  selenium.open("/");
                  verifyTrue(selenium.isElementPresent("link=About Us"));
                  verifyTrue(selenium.isElementPresent("link=FAQs"));
                  verifyTrue(selenium.isElementPresent("link=FAQs"));
                  verifyTrue(selenium.isElementPresent("link=Support"));
                  verifyTrue(selenium.isElementPresent("link=Customer Forum"));
                  verifyTrue(selenium.isElementPresent("link=Blog"));
                  verifyTrue(selenium
                              .isElementPresent("link=Cleartrip for Business"));
                  verifyTrue(selenium.isElementPresent("link=Privacy"));
                  verifyTrue(selenium.isElementPresent("link=Security"));
                  verifyEquals("Security", selenium.getText("link=Security"));
                  verifyTrue(selenium.isTextPresent("API"));
                  verifyTrue(selenium.isTextPresent("Terms of Use"));
                  verifyTrue(selenium.isTextPresent("Privacy"));
                  verifyTrue(selenium.isTextPresent("Cleartrip for Business"));
                  verifyTrue(selenium.isTextPresent("Blog"));
                  verifyTrue(selenium.isTextPresent("Customer Forum"));
                  verifyTrue(selenium.isTextPresent("Support"));
                  verifyTrue(selenium.isTextPresent("About Us"));
            } catch (Exception e) {
                  System.out.println("Exception Occurred " + e.toString());
            }

      }

      /* Data Provider for oneway flight Search */
      @DataProvider(name = "dataProviderSearchFlightsOneWay")
      public Object[][] setDataforSearchFlightsOneWay() {
            System.out.println("Start Data Provider: SearchFlightsOneWay");
            Object[][] retkeyword = { { "MAA", "BLR" }, { "MAA", "BOM" } };
            System.out.println("End Data Provider: SearchFlightsOneWay");
            return (retkeyword);
      }
}

Please find snapshot of files in this project. Please download them from previous post.
This may not be perfect code but this is one step ahead of my previous code. Many thanks to Tarun for his feedback for previous post.

More Reads
Taking Remote Screenshots With Selenium And The Robot Framework
Taking Snapshots
Parameterization of Selenium Tests with Microsoft Excel

Happy Reading!!!

October 22, 2011

Going with 'Google Cloud SQL'

I signed up for Google Cloud SQL. This post is for 'Getting Started with Google Cloud SQL'.
To get started, Documentation is available in link

This Database Cloud is based on MySQL database. I want to retry exercise posted earlier. To tryout logon to Google API console

After logging in Google API console you need to create Project.


I want to try basic tasks (Creating instances).


After creating instance you can check Dashboard to see Database Size, Version properties. SQL Prompt provided is the console to start executing MySQL commands
Next is playing with MySQL basic commands

Step 1 - Creating Database
Step 2 - List Database
Step 3 - Creating a Table

Step 4 - Created and Executed below stored procedure

CREATE PROCEDURE dowhile() 
BEGIN 
DECLARE I INT DEFAULT 5; 
v1loop: WHILE I < 10000 DO    
INSERT INTO TestTable1(A,B,C,D)    
SELECT CONCAT(I,'A'), CONCAT(I,'B'), CONCAT(I,'C'), CONCAT(I,'D');    
SET I = I + 1; 
END WHILE v1loop; 
END

It took atleast 10 minutes to complete executing the procedure. My desktop MySql version was comparitevly faster.
Step 5 - SELECT query
Step 6 - Checking Execution Plan

I didn't see any execution plan details with Explain Command.

This SQL Prompt was pretty slow compared to my dekstop edition of mysql. Next task is to learn other Google API's and build a sample app on top of it.

Happy Learning!!!

October 16, 2011

SOASTA Functional Testing Webinar Notes

I had signed up for Webinar - SOASTA Functional Testing Webinar. I couldn't attend it. Offline version is available in link

Webinar Notes
  • Tool evolved as need for Better Test Results Reporting, Faster Development of Test Automation Code, Better IDE
  • SOASTA Tool - CloudTest is based on Selenium. (SauceLabs also provides Cloud based test tool based on Selenium)
  • Single Platform for Functional & Performance Testing of Web & Mobile Apps
  • Cloud Lite Free versions provides tests with (100 Users Limitation, Single Location)
  • Demo of a Record - Playback scenario of a website
  • Tool provides options for generating XPath (I would love this feature :))
  • Inbuilt Results Reporting providing Test Execution Details Time, Tests executed, Duration
  • From FAQ Link, Cost Factor - Hourly rate for tests start at $850/hr

More Reads
Webdriver Architecture Overview

You may also like - Testing in the era of Cloud Computing. Browser mob, SOASTA are based on AWS.  Please check interesting presentation


 
Happy Learning!!!

NOSQL Updates & Database Products Update

I follow brentonzar blog for SQL updates. Latest SQL 2012 features please check post

Consolidating list of other interesting news on databases
  • Oracle is going to provide connectors for NOSQL Databases (Link)
  • Oracle develops its own version of NOSQL Database (Link)
  • SQL Server 2012 is going to provide connectors for NOSQL and Hadoop Databases (Link)
  • Column based storage concept seem to be in roadmap for both SQL Server and Oracle, SQL Server provides column storage option for tables (link).
  • Oracle also mentioned data compression by storing data as columns than as rows (Link)
Lots of Intersting news and Updates supporting and consolidating data from NOSQL Databases

Happy Reading!!

October 06, 2011

Tool for the Day - Technology Stack of Website

If you want to know Web technologies used by a website, You have a tool for it

Go to this link. Provide the website name and click on siteinfo, you would see details of
  • Server Side programming language
  • Web Server details
  • Client Side programming language and other details
I tried for couple of sites. This is a Cool Tool!!

MongoDB Webinar Notes

Attended MongoDB: A Quickstart Tutorial by 10gen services 

Summary of Notes from the Meeting 
  • MongoDB - Primary datastore for web apps. Couple of examples on sites run using MongoDB was provided (ex-foursquare)
  • Demo - Developing Location based Application, Query near by places (Restaurants)
  • Data is stored as Documents. Key value pair based storage
  • Data stored within collection has no schema defined, Generally Each collection will be similar information stored. 3 collections (tables) - places, users, checkins.
  • MongoDB has built in support for geo location queries
  • For each record, Tips fields was added (store tags) for data inserted. This would be used for record retrieval based based on tag value
  • MongoDB supports Regular Expression in queries
  • MongoDB Query Operators have $ symbol ($gt - greater than, $lt - less than etc..)
  • Constraints option is not available in MongoDB (Primary Key/Foreign Key)
  • No concept of Isolation levels in MongoDB
  • Composite Indexes (Indexes based on multiple columns) supported in MongoDB
  • Aggregation group by functionality would be provided in 2.0 release
  • MongoDB has no built in encryption support
  • Availability and Scalability options
  • Replica set support (Single primary and multiple secondary systems)
  • Autosharding to achieve scalability. Routes partitions data into groups based on fields in documents
We have covered couple of examples (Table Creation / Inserting Records / Select Query / Index) in previous post. Composite Indexes, Tags, Query Operators, Geographical data support are new learning's from this session.

Good Reads
no:sql(eu) and NoSQL: What’s the deal?
Let’s play with Cassandra… (Part 1/3)
Hadoop Distributed File System : Overview & Configuration

Happy Learning!!

October 05, 2011

NOSQL - can it replace RDBMS Databases?

[You may also like - Big Data - Basics - Getting Started

NOSQL Databases are quite popular last couple of years. Will it replace RDBMS databases? What are their advantages? I have been working in SQL Server for last 5 years. Do I need to learn NOSQL as well?

First to get answer for this question, I need to understand

Ø  What NOSQL Provides
o   No Strict Schema. Store New Data without considering earlier stored data types
o   Provide Indexing, Querying features same as a RDBMS
o   Distributed Caching etc..
This link provides good read on Disadvantages of RDBMS databases. Also check whitepaper on NOSQL Technology from CouchBase site.

I want to do a few things on a NOSQL Database. I tried with MongoDB. Downloaded 32 bit Windows Installer. Unzipped the files. Detailed Steps provided in link

After creating Data directory, Run mongod.exe


Next is running Mongo.exe


Now we can try sample examples
  • Creating Table - Yes supported
  • Storing records - Yes supported
  • Execution plan - Yes supported
  • Stored Procedures – Javascript code in MongoDB. Good Read link
  • SQL Joins are not supported in MongoDB link
  • Triggers - Not Supported link
  • Indexes - Yes
This link SQL - MongoDB Mapping Chart was very useful to try our example. Reusing Schema created in link

Step 1 - Table Creation


Step 2 - Inserting Record and Selecting Records


Step 3 - Checking Execution Plan



Step 4 - Drop a collection
--Equivalent to Dropping a Table in TSQL

db.Earnings.drop();

Step 5 - Inserting Records
-- Creating Table
db.createCollection("Earnings");

db.Earnings.insert({Name:"Raja",SaleDate:"10/05/2011",SaleValue:12500,City:"Chennai", tags:["BestPerformer","top10"]});
db.Earnings.insert({Name:"Raja",SaleDate:"10/07/2011",SaleValue:5500,City:"Chennai",tags:["BestPerformer","top40"]});
db.Earnings.insert({Name:"Raja",SaleDate:"10/09/2011",SaleValue:8500,City:"Mumbai",tags:["BestPerformer","top20"]});
db.Earnings.insert({Name:"Robert",SaleDate:"10/05/2011",SaleValue:2500,City:"Hyderebad",tags:["AveragePerformer","top50"]});
db.Earnings.insert({Name:"Robert",SaleDate:"10/07/2011",SaleValue:7500,City:"Hyderabad",tags:["BestPerformer","top20"]});
db.Earnings.insert({Name:"Robert",SaleDate:"10/09/2011",SaleValue:8500,City:"Chennai",tags:["GoodPerformer","top30"]});
db.Earnings.insert({Name:"Allen",SaleDate:"10/05/2011",SaleValue:6500,City:"Delhi",tags:["AvgPerformer","top50"]});
db.Earnings.insert({Name:"Allen",SaleDate:"10/07/2011",SaleValue:6500,City:"Hyderabad",tags:["AvgPerformer","top50"]});
db.Earnings.insert({Name:"Allen",SaleDate:"10/09/2011",SaleValue:6500,City:"Bangalore",tags:["MediumPerformer","top70"]});

Step 6 -Listing all records

db.Earnings.find();

Step 7 - Select only few columns

db.Earnings.find({},{Name:1,City:1,SaleDate:1});
db.Earnings.find({},{Name:1,City:1,SaleDate:1});

Step 8 - Find all best performers based on tags

db.Earnings.find({tags:"BestPerformer"});
db.Earnings.find({tags:"top10"});

Step 9 - Is it case Sensitive ?

db.Earnings.find({tags:"bestperformer"});
Yes, It is case sensitive, Zero Records returned for above query

Step 10 - Using Regular Expressions
--Find all employees who name starts with R

db.Earnings.find({Name:/^R/});

Step 11 - Update Records

db.Earnings.update({Name:"Raja"}, {$set:{Name:"Raja NewName"}},false, true);

Step 12 - Using Query operators

db.Earnings.find({SaleValue:{$gt:8000}});
db.Earnings.find({SaleValue:{$gt:8000}},{Name:1,City:1,SaleDate:1,SaleValue:1});

Step 13 - Delete a record

db.Earnings.remove({City:"Chennai"});

Step 14 - Execution Plan without Index

db.Earnings.find({City:"Chennai"}).explain();

Step 15 - Execution Plan with Index

db.users.ensureIndex({City:1});
db.Earnings.find({City:"Chennai"}).explain();
I didn't see much difference between both the queries. Records are very less in our case. It would be good to try it with a larger data set

The next question that comes in my mind is - Can I use NOSQL DB for OLTP Application?
Stackoverflow question Which NoSQL DB is best fitted for OLTP financial systems? was the best answer I could find for my question
The aspects highlighted are
  • Consistency
  • Database Integrity
Facebook, Twitter – Social Networking Sites dealing with Data related to individuals. Data collected is
  • Check on Consistency / Integrity of Data may not be a priority as its mostly demographic information, interests, friends, hobbies etc.. related information is captured
  • Distributed Caching enables faster query and data retrieval for end user
  • Not Financial/Secure information/Trasnsactions (ex-Banking details of user)
Learning’s
  • Examples above would show MongoDB equivalent syntax for TSQL statement. Learning curve looks pretty straight forward
  • Based on the need you may decide SQL or NOSQL
    • Ordering Details of ecommerce site is best suited to be on RDBMS SQL platform to maintain Data Integrity, Consistency
    • Listing items / Managing Recommendations / Searching Inventory can be based on NOSQL databases
  • For BI platform, NOSQL can be a Datasource. Data Quality/ Data Cleaning Process – ETL has to be done on NSQL databases to clean-up data issues/ fix Integrity/Consistency issues in the NOSQL Databases. It would be a good learning to see a whitepaper/case study on BI Analytics on NOSQL Database
In a Nutshell, NOSQL - can it replace RDBMS Databases?
  • Yes for certain aspects (Non Critical features of OLTP App). Example - For of a web application (Listing items / Managing Recommendations / Searching Inventory/Product Reviews/Managing Customer Contacts) can be stored on NOSQL databases
  • RDBMS would still be preferred option for Ordering / critical financial related transactions (ex-online banking, online shopping – payments)
  • For BI – NOSQL *NO*, If NOSQL providers come up with additional tools/features for BI reporting on top of NOSQL then it would be worth to take a look
Predicted market share of NOSQL DB by 2015 - $1.8Bln. (Source)
Slightly Deviating from the topic, let’s see Databases used by product companies, PB Databases (1 Petabyte DB = 1000 Tera byte). Sneak peek into What DBs are used by product companies

  • Google - MySQLdb, Big Table
  • AOL - Oracle, Sybase, PostgreSQL, MySQL
  • AT&T Research - proprietary DB called Daytona
  • Ebay – Teradata
  • YahooOracle, HBASE (DB over Hadoop)

Source - Link. This is few years old. They might have moved to NOSQL for certain areas.

More Reads
Please feel free to add your comments.

June 2020
HSBC moves from 65 relational databases into one global MongoDB database

Data Information - 60 countries and serving more than 40 million customers
  • MongoDB JSON schema model
  • MongoDB's document model
  • Single collection, using sub-documents
  • Country specific identifiers
  • Database is schema-less and provides powerful querying and indexing
Happy Learning!!!