public interface AutomatedTesting
Smart GWT includes free support for Selenium for robust recording and playback of tests, including the ability to record on one browser and play back on others, via Selenese enhanced with Smart GWT-specific locators and commands that provide a stable means of locating Smart GWT widgets and ensuring they're ready for interaction.
To write Selenese, we recommend Selenium IDE 2.9, which is compatible with
Firefox 52
ESR, and
can directly load our user extensions, located in the
selenium/
directory. A user guide explaining how to create and interactively run selenese with the IDE
can be found here
. Selenium IDE 3, which
requires Firefox
Quantum, has just released support for plugins that should allow the eventual migration of
our user extensions, but for now only Selenium IDE 2.9 can load Smart GWT locator and
command extensions.
SeleneseRunner
For automated testing, Smart GWT provides
SeleneseRunner, a tool that
executes Smart GWT-enhanced Selenese created by Selenium IDE via emulation, since Selenium
3 no longer supports the Selenium RC APIs and thus can't execute Selenese that requires
custom user extensions. Internally, SeleneseRunner
makes use of the APIs in
our WebDriver wrappers to resolve locators properly and execute Smart GWT-enhanced
Selenese.
SeleneseRunner
can be used to:
See the server-side JavaDoc linked above for more information on how to use these features.
TestRunner
is a system for automatically running a
suite of Selenium
tests, commiting the results to a database, and reporting any regressions (or fixes) via email.
GWT includes a way to run a GWT application under JUnit, running your GWT application in a "headless" browser. This is a very limited testing approach appropriate for certain unit tests only - it cannot replace events such as clicks, because by default it doesn't run in actual browser (instead it runs in a simulator called HtmlUnit).
Note that running tests under HtmlUnit can lead to false failures in a variety of areas, including network communication and XML processing, where HtmlUnit's behaviors do not correspond to any real browser. Note that, if you find that a test fails under HtmlUnit but would not fail in a real browser, this will not be regarded as a SmartGWT bug.
If you use GwtTestCase at all, Isomorphic recommends that the majority of your tests are executed using the runStyle option that allows GwtTestCase to run under a real browser via Selenium.
Also note, GwtTestCase has a bug where it does not run onModuleLoad() for included GWT
modules. To make sure SmartGWT's onModuleLoad() runs, add a gwtSetUp()
implementation like so:
public class SgwtTest extends GWTTestCase { public void gwtSetUp() { new SmartGwtEntryPoint().onModuleLoad(); } ...
You may need to add similar manual calls for other GWT modules you inherit which expect to
have their onModuleLoad()
method called normally.
WebDriver, supported since Selenium 2, uses a different basic architecture in which a driver is added to each browser to enable Selenium interaction, instead of doing so from JavaScript.
Support for WebDriver-based testing for Smart GWT is now available with the same custom
locator strategies and custom commands as we provide for Selenese. However, we continue
to recommend Selenese rather than WebDriver-based Selenium, because Webdriver requires
Java programming skills. Tests created in Selenium IDE and stored in Selenese can be
executed by a variety of tools without requiring Java skills, including our own
TestRunner
. Most ways of running WebDriver tests involve Java
coding skills or
at least the ability to work with a Java IDE. This tends to mean that all QA personnel must
either have Java skills or drain the time of Java developers on repetitive tasks.
Ultimately, our current recommendation is to use Selenium IDE and Selenese exclusively or at least primarily. If there are critically important tests that you can only build via WebDriver, use WebDriver for those tests only, or use manual testing for those tests.
WebDriver Usage
When using WebDriver, we recommend using Selenum IDE as a starting point to record and store
tests. You can then call SeleneseRunner
to convert that Selenese to Java code
that uses Smart GWT locators and invokes the appropriate APIs on our WebDriver wrappers.
Once you become familiar with what code is generated for common interactions, you may want to
write tests directly without using Selenium IDE. In this case, you can use the
AutoTest
APIs, such as AutoTest.getLocator()
, which takes a Canvas
or
DOM element, to get the locators you need from the Developer Console
.
NOTE: Selenium IDE has an option to export tests as WebDriver-compatible code. Do
not use this feature, it exports useless code that doesn't understand custom commands,
custom locators, or other key features of Selenium IDE. Use SeleneseRunner
instead.
WebDriver Classes overview
Storing and executing Selenese tests recorded in the Selenium IDE is recommended as the primary approach for using WebDriver. However, for certain rare tests it can make sense to use WebDriver Java support directly.
Smart GWT support for WebDriver is based around 3 different Java classes:
UsingSelenium
for more
background on Locator strings and how to obtain them. Given a locator String, example usage
is:
ByScLocator.scLocator("//ListGrid[ID=\"countryList\"]/body/row[countryCode=US||0]/col[fieldName=countryCode||0]")
These classes are packaged in the library isomorphic_webdriver.jar, which can be found in the directory lib-WebDriverSupport (along with several 3rd-party supporting libraries).This directory can be found at the top level of the downloaded Smart GWT zip package.
General information regarding WebDriver can be found here. Setup for WebDriver is more complex than for classic Selenium. Drivers can be downloaded for Firefox, Google Chrome, Internet Explorer, and MS Edge.
JUnit + WebDriver
Explore JUnit + Selenium WebDriver
, where we
walk through a JUnit test
targeting a Smart GWT Showcase sample.
File Upload Example Test
As discussed above, one advantage which WebDriver does have over Classic Selenium is the ability to test file upload. It is still limited in that if a click is triggered on the file selection button an OS native file selection dialog will be triggered in which case the test will be suspended until the file is manually selected. To avoid this, the sendKeys() method can be used to enter the file location.
Sample code:
/** * The following test runs against localhost and requires a small (< 5mb) image to be in /tmp/image.jpg */ public void fileUploadGWT() throws Exception { final String basePath = "//VLayout[ID=\"isc_Showcase_1_0\"]/member[Class=HLayout||index=0||length=2|" +"|classIndex=0||classLength=1]/member[Class=HLayout||index=0||length=2||classIndex=0|" +"|classLength=1]/member[Class=Canvas||index=1||length=2||classIndex=0||classLength=1]" +"/child[Class=TabSet||index=0||length=1||classIndex=0||classLength=1]/paneContainer/" +"member[Class=VLayout||index=1||length=2||classIndex=0||classLength=1]/" +"member[Class=VLayout||index=1||length=2||classIndex=0||classLength=1]/" +"member[Class=HLayout||index=1||length=2||classIndex=0||classLength=1]/" +"member[Class=HLayout||index=0||length=1||classIndex=0||classLength=1]/"; final String formPath = basePath + "member[Class=DynamicForm||index=0||length=3||classIndex=0||classLength=1]"; final String tilesPath = basePath + "member[Class=VLayout||index=2||length=3||classIndex=0||classLength=1]/" + "member[Class=TileGrid||index=2||length=4||classIndex=0||classLength=1]/tile"; SmartClientWebDriver driver = new SmartClientFirefoxDriver(); driver.setBaseUrl("http://localhost:8888/"); driver.get("index.html#upload_sql", true); final int origSize = driver.findElements(ByScLocator.scLocator(tilesPath)).size(); By uploadForm = ByScLocator.scLocator(formPath); WebElement form = driver.findElement(uploadForm); By titleInput = ByScLocator.scLocator(formPath + "/item[name=title||title=Title||index=0||Class=TextItem]/element"); driver.click(titleInput); driver.sendKeys(titleInput, "test image: " + origSize); WebElement findElement = form.findElement(By.xpath("//input[@type='FILE']")); /* * The following causes a native dialog to be created which prevents further progress. Do NOT uncomment! * We just have to sendKeys() to it */ //findElement.click(); findElement.sendKeys("/tmp/image.jpg"); // A local file. Please change accordingly By saveButton = ByScLocator.scLocator(formPath + "/item[title=Save||index=2||Class=ButtonItem]/button/"); driver.waitForElementClickable(saveButton); driver.click(saveButton); /* * Note the following fails once the grid contains more than 3 rows of data as the index becomes inconsistent * as tiles scrolled out of site are removed and the indices change */ By tile = ByScLocator.scLocator(tilesPath + "[Class=SimpleTile||index="+(origSize)+"||length="+(origSize+1) + "||classIndex="+(origSize)+"||classLength="+(origSize+1)+"]/"); driver.waitForElementClickable(tile); WebElement tile1 = driver.findElement(tile); assertEquals("test image: " + origSize, tile1.getText()); assertEquals(origSize + 1, driver.findElements(ByScLocator.scLocator(tilesPath)).size()); driver.close(); driver.quit(); }
WebDriver Troubleshooting
There is a known issue that native events do not work with IE in Windows 8/8.1 that may manifest in WebDriver as clicks having no effect. One potential workaround is to disable native events:
DesiredCapabilities caps = DesiredCapabilities.internetExplorer(); caps.setCapability("nativeEvents",false); SmartClientWebDriver driver = new SmartClientIEDriver(caps);It's also been reported that changing the second line above to:
caps.setCapability("requireWindowFocus", true);also resolves the issue, with the side effect that WebDriver then moves the mouse cursor.
In some versions of Internet Explorer, it's been reported that you must add the URL targeted by WebDriver to the "Trusted Sites" under Internet Options >> Security in order to allow the browser to communicate properly with Selenium. A discussion of the setup needed to use WebDriver's InternetExplorerDriver can be found here.
Other tools
Smart GWT supports a special JavaScript API to allow other test tools to integrate in the same manner as Selenium and WebDriver. This API allows the test tool to record an abstract "locator" string representing the logical name for an interactive DOM element, and then during test playback, retrieve a DOM element given a locator.
This is critical because, like many modern Ajax systems, Smart GWT generates different DOM elements in different browsers, in different skins, and in different versions of Smart GWT. Testing tools that try to directly record the generated Smart GWT DOM produce extremely brittle tests because they are effectively recording undocumented internals.
Using the "locator" API allows you to record or write tests that will run in any browser supported by Smart GWT, in any version of Smart GWT, and in any skin. It also makes tests more readable and easier to understand and maintain.
Different testing tools vary in how easily they can be configured to use the locator API, and in some older tools it can be a large effort. We highly recommend using our Selenium extensions - it often makes sense to use them even if you have to use them in parallel with another, older testing tool. If you are forced to use another tool exclusively: