Testing SmartGWT Applications with Selenium and Robot Framework - codecentric AG Blog

:

We started to use SmartGWT for our GWT project a couple of weeks ago. SmartGWT provides a lot of powerfull widgets and is simple to use. The SmartGWT showcase has a lot of example code, which makes the developer happy. And after our first Sprint Review, our customer was very satisfied with the new GUI.

BUT… As you may know, quality is a key fact of our Agile Software Factory. So we started to create our acceptance tests based on Selenium and the Robot Framework as we did it in many projects before. Unfortunately that was not easy and we had to do some additional work to get it run. In this blog I want to share some tipps and tricks about using Selenium and Robot Framework with SmartGWT.

As we first started to record some testcases with Selenium IDE, we mentioned that nothing was working during replay. SmartGWT creates some very high complex HTML structures. Key problems are locating the widgets and firing right browser events to get SmartGWT working.

SmartGWT starts supporting Selenium from version 2.2. and provides some user extensions for Selenium. This user extension can be integrated in Selenium IDE and also for automatic tests in the Selenium Server.

If you are interested in the details, you can have a look into selenium-api.js. This is the original version of Selenium and you can find the implementation for every command, for example doClick(). This implementation is not sufficent for SmartGWT. You can find the user extension.js in the SmartGWT 2.2 download package under /selenium/user-extension.js. This user extension extends the original functionality of Selenium and fires for example some additional events (Mouse-Up, Mouse-Down).

Example:

this.browserbot.triggerMouseEvent(element, "mousedown", true, clientX, clientY);
this.browserbot.triggerMouseEvent(element, "mouseup", true, clientX, clientY);
this.browserbot.clickElement(element);

this.browserbot.triggerMouseEvent(element, "mousedown", true, clientX, clientY); this.browserbot.triggerMouseEvent(element, "mouseup", true, clientX, clientY); this.browserbot.clickElement(element);

The user extension also introduces a new locator scLocator, like the existing locators in Selenium (xpath, css, id). All special-handling for SmartGWT-components from the user extension are only used, if you use a scLocator to locate the elements. Otherwise it will just use the default behaviour or, to be more precise, it SHOULD use the default behaviour. We are using a user extension version from the nightly build of SmartGWT 2.3 and changed a view lines of code, to get it finally working.

ID’s

Add some meaningful ID's to your code. Otherwise you will use ID's which are generated by SmartGWT and can be different after a fresh build.

Examples:

Button searchPerson = new Button(MESSAGES.personBt());
searchPerson.setID("searchPerson");

Button searchPerson = new Button(MESSAGES.personBt()); searchPerson.setID("searchPerson");

ListGrid hitList = new ListGrid();
hitList.setID("hitList");

ListGrid hitList = new ListGrid(); hitList.setID("hitList");

Use Selenium IDE

Selenium IDE helps a lot to write testcases. Use the right-click to add some verify’s and get an idea of the locators. If you configured the user-extension-ide.js, Selenium IDE will also suggest some of the new scLocator’s. But before using the scLocators in your test-script, be sure to strip them a little bit to have a clean script.

For example this

scLocator=//DynamicForm[ID="doSearchForm"]/item[name=mainRegisterBox||title=Main%20Register||index=0||Class=ComboBoxItem]/element

scLocator=//DynamicForm[ID="doSearchForm"]/item[name=mainRegisterBox||title=Main%20Register||index=0||Class=ComboBoxItem]/element

can be stripped to

scLocator=//DynamicForm[ID="doSearchForm"]/item[name=mainRegisterBox]/element

scLocator=//DynamicForm[ID="doSearchForm"]/item[name=mainRegisterBox]/element

Robotframework

If you are using the Robot Framework, you cannot use all keywords from SeleniumLibray. Keywords, which are definitely working are “Call Selenium Api”, “Execute JavaScript” and “Wait For Condition”.
To get the keywords of the SeleniumLibray running, you have to add a location stratgey to the robotframework. (see comments 1 and 2)

Examples:

Call Selenium Api  click  scLocator=//Button[ID="searchPerson"]/

Call Selenium Api  click  scLocator=//Button[ID="searchPerson"]/

Call Selenium Api  verifyTable  scLocator=//ListGrid[ID="hitList"].0.0  05/20/2010

Call Selenium Api  verifyTable  scLocator=//ListGrid[ID="hitList"].0.0  05/20/2010

Use JavaScript

If it becomes to hard, to implement your tests with scLocators, you can just use JavaScript! Remember, your java client code get’s translated into JavaScript. That’s why you can use a lot of methods for testing.

Examples:

Execute JavaScript  window.hitList.selectRecord(2);

Execute JavaScript  window.hitList.selectRecord(2);

Execute JavaScript  window.hitList.deselectAllRecords();

Execute JavaScript  window.hitList.deselectAllRecords();

Use Firebug to test your JavaScript-expressions

Firebug provides some nice features to evaluate your javascript expressions. Sometimes there is also code completion, if you don’t know the methods provided by your widget.

Use WaitFor instead of Sleep

As we started to write acceptance tests for our GWT application, it was full of “Sleep  2s”. Because GWT works with ajax requests, you can never know exactly, when your GUI will change. There is no new page, which is the concept of Seleniums xxxAndWait-Keywords. The sleeps are working, but it slows down the tests. Better use some WaitFor-conditions with timeouts.

Examples:

Wait For Condition  window.hitList.data.length == 5  2000

Wait For Condition  window.hitList.data.length == 5  2000

Wait For Condition  window.confirmBox.isVisible() == true  2000

Wait For Condition  window.confirmBox.isVisible() == true  2000

Call Selenium Api  waitForElementPresent  scLocator=//ListGrid[ID="hitList"]/body/row[0]/col[0]  2000

Call Selenium Api waitForElementPresent scLocator=//ListGrid[ID="hitList"]/body/row[0]/col[0] 2000

Last but not least

Don’t mix classic GWT with SmartGWT. That has nothing to do with testing. It’s just not really compatible. Layouting your application is very hard with this mixed approach. We tried it first and switched to pure SmartGWT after that.