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).
this.browserbot.triggerMouseEvent(element, "mousedown", true, clientX, clientY);
this.browserbot.triggerMouseEvent(element, "mouseup", true, clientX, clientY);
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.
Tipps and Tricks about writing tests
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.
Button searchPerson = new Button(MESSAGES.personBt());
ListGrid hitList = new ListGrid();
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
can be stripped to
To get the keywords of the SeleniumLibray running, you have to add a location stratgey to the robotframework. (see comments 1 and 2)
Call Selenium Api click scLocator=//Button[ID="searchPerson"]/
Call Selenium Api verifyTable scLocator=//ListGrid[ID="hitList"].0.0 05/20/2010
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.
Wait For Condition window.hitList.data.length == 5 2000
Wait For Condition window.confirmBox.isVisible() == true 2000
Call Selenium Api waitForElementPresent scLocator=//ListGrid[ID="hitList"]/body/row/col 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.