follow me icons

Saturday, December 18, 2010

QTP VS Selenium Webdriver and Cucumber

My company was using QTP to do the test automation for the past 3-4 years. But we are now moving to cucumber and selenium Webdriver. This blog is about why we are moving away from QTP in my company.

One of the main reason that we move from QTP is that it is a reactive approach of writing test automation. The product is finished and the tester starts writing the automation test. Only the tester writes the automation. With cucumber and selenium , writing automation test is a joint effort between the developers and the testers. The testers write the test cases in cucumber scenario format, then the developers write the steps definition. This way, everyone is contributing and everyone is reviewing the test cases.

In our case, our QTP automation tester left the company and the QTP vbs code is hard to maintain and to read compared to cucumber and ruby code. I have tried to read QTP code to try to convert the test to cucumber and it is just taking quite a lot of time to just understand what the scripts do. With cucumber, selenium webdriver reading what the tests do only take 1-2 minutes as cucumber scenarios describe the behaviour of the system. With cucumber and selenium, everyone is contributing to the automation code and therefore knowledge is being transferred all the time.


QTP is very costly while cucumber, selenium webdriver is free.

Is there any version control in QTP? In our case, we put the automation test code (cucumber, selenium webdriver) as part of the system source code so the automation code is sourced controled.

We can develop the automation code in Windows, Ubuntu, Mac or in any other platforms that you like. This is another topic, but in our case everyone is moving away from windows as well especially the developers which is why QTP is abit useless as you can use Windows only.

Continous Integration is also an ease. We use hudson to automatically run the automation test whenever there is a new build so the developers can get an instant feedback of their changes.

Selenium webdriver can do alot more tests than the previous version (selenium rc) including java script requests and ajax test.

Getting a support answer is very fast in the open source community. Also, you have access to the source code. Since it is a joint effort to write the automation test, we are able to solve alot of issues together.

Other IT departments in our company are already ditching QTP in favor of cucumber and selenium and we never want to go back to QTP after this.

I believe QTP have other benefits as well that I do not know. However, in our case using cucumber and selenium webdriver is more relevant and better than using QTP.

Friday, December 17, 2010

How to change .RubyMine config default directory location

I am using a JetBrains RubyMine ide to write and develop the test automation. RubyMine has provided alot of useful features for developing Cucumber in Ruby such as providing the function to easily find the steps definition from the cucumber scenario.

My work computer is using a desktop profile space which only allow me to store 2mb of data. Unfortunately, RubyMine by default stores all of the RubyMine config ".RubyMine20" in the default directory which is usually under your own folder. This RubyMine default directory happens to be in my desktop profile and I don't have the privilege to change/remove the desktop profile. This causes a lot of inconveniences for me since I have to delete the .RubyMine20 folder every time I shutdown my computer. It is very annoying.

I finally found out that you can change the .RubyMine20 default directory. You would need to change the "idea.properties" file which is usually located under your RubyMine\bin\idea.properties folder. In my case, it is located in "C:\JetBrains\RubyMine\bin\idea.properties".

Once you open the idea.properties file, you need to change the following variables:

idea.config.path="D:\your_new_directory\.RubyMine20\config"
idea.system.path="D:\your_new_directory\.RubyMine20\system"
idea.plugins.path="D:\your_new_directory\.RubyMine20\config\plugins"

Friday, December 10, 2010

WebDriver Error - Element is no longer attached to the DOM (Selenium::WebDriver::Error::ObsoleteElementError)

I have been getting this error message for a while now and it is very annoying. The reason it is very annoying is because the error is not always reproducible. The ObsoleteElementError only happens about 1 out of 8-10 times I run my test.

After tracing down the errors I found out the code that causes the error:


find(:css, "#travel_control").click
find(:xpath, ".//*[@id='field_container']/a[#TRAVEL_MODE_INDEX[travel_mode]}]").click


It seems that Web driver could not find the #travel_control element and therefore it throws the ObsoleteElement Error. The #travel_control element in my test is actually an ajax call on a popup box so probably WebDriver still has some issue in handling elements with ajax request and javascript.

Nevertheless, I found some help from google groups regarding this issue. There does not seem to be a solution in that thread but there is one comment regarding a temporary fix for this issue which is to ignore the error and execute the same code again.

So I tried it and changed my code into:


begin
find(:css, "#travel_control").click
find(:xpath, ".//*[@id='field_container']/
a[#{TRAVEL_MODE_INDEX[travel_mode]}]").click
rescue Selenium::WebDriver::Error::ObsoleteElementError
find(:css, "#travel_control").click
find(:xpath, ".//*[@id='field_container']/
a[#{TRAVEL_MODE_INDEX[travel_mode]}]").click
end


However, This does not work for me and instead I get this error


Element is not currently visible and so may not be clicked (Selenium::WebDriver::Error::ElementNotDisplayedError)


It turns out because when I get the ObsoleteElementError, WebDriver actually is able to click the "#travel_control element. so what I need to change is to not click the same element again. Here is how I fix my test:


begin
find(:css, "#travel_control").click
find(:xpath, ".//*[@id='field_container']/a[#{TRAVEL_MODE_INDEX[travel_mode]}]").click
rescue Selenium::WebDriver::Error::ObsoleteElementError
#just execute the next element
find(:xpath, ".//*[@id='field_container']/a[#{TRAVEL_MODE_INDEX[travel_mode]}]").click
end