Saturday, November 30, 2013

AF Gradle

AfGadle is a Gradle extension of AfAnt, with the aim of replacing all of it. Ant is too cumbersome of a build language, for example AfAnt is almost 3000 lines of Ant macros and associated Java classes. Ant code gets really whacky when dealing with functionality likes methods, iterations, and so on. For this reason no one dares to touch it. Gradle is easier to understand, easier to write, easier to maintain, and easier to test.

Import Points of Support


  • Database Versioning - We have gotten in the habit of using dbdeploy to version databases, and now that I have had it in place for several years I don't know how we every got by without it. With any production system you can't simply add, update, and remove columns and data at will, because you have to take into account the consequences on the existing data. Manually applying database updates is a time consuming and error prone process, where dbdeploy's process lets you do it automatically. If there is an issue and the update fails, the transaction is rolled back. If you realized 3 days later that you made a mistake, you just manually apply the rollback script that was generated with the update script. If you ever want to achieve continuous deployment and/or continuous delivery, automatically performing database updates (in a way that doesn't require you to drop and re-create your database) is a must.
  • Test Data Set Management - Managing test data in this circumstance is larger than just supplying data at the unit and integration level, the concern is for all the data in the system. What data do we use in the development environment, what data do we use in the QA environment, and what data do we use in pre-production? In development you typically use a light data with the minimum required for operation. In QA you let the testers build on the development data set, and create a backup of it on every deployment so that they can rollback if something gets messed up. Pre-production when possible should be a clone of the data in production, usually a few days old depending on the size of the database. We use dbunit to handle the exporting and importing of the data in databases from flat files, because this ends up being quicker and easier to manage than imaging and/or cloning databases.
  • Specific Database Driver Support - Tools like dbunit and dbdeploy don't play nicely out-of-the-box with every RDBMS, specifically MS SQL. I have had to extend and override dbunit support in a lot of cases for MS SQL support for things like auto generated primary keys and non-editable time stamps. MySQL mostly works with dbunit, with the only extension being the use of table names as a single parameter (comma separated) instead of element declarations. This was done so that table names could be stored in a property file.
  • External Property File Management - A common technique used in development environments is for the developer to provide a property file in their home directory that defines environment specific settings such as database connection information. Gradle doesn't easily allow this, so an extra task was added to allow the specification of zero to many property files for a build.
  • Mongo DB Support - dbdeploy doesn't apply to the way most people use Mongo for file storage, and it otherwise does a good job at adding a removing attributes when needed. There isn't native build system support for the import, export, and creation of mongo databases. For this reason Gradle tasks were created that allow you to do this, without having to deal with the command-line operation of Mongo. The command-line operation of mongo is also not straight forward, especially when dealing with securing data access with a username and password. The Gradle tasks deal with installing/uninstalling Mongo as a username/password protected service along with creating databases with specific access controls.
  • Better Ant Integration - Builds for the near future will inevitably still be dependent in some way on Ant libraries. For this reason tasks and closures were added to more easily support Ant integration. Specifically the underlying library dependencies for dbunit, dbdeploy, and others are built into the plug-in, so you don't have to worry about them. There are also closures for more easily pulling in an Ant JAR as a dependency, which is less verbose.
  • Integration Testing tied to Data Set Management - This is the concept where you setup the integration testing environment with a predefined data set, which defines all system data. The other approach is to skip this entirely and just use the dbunit support at the test method level.
  • JavaScript/CSS Minification - Shrinking the size of these static files is an important part of deploying web applications, especially when dealing with large deployments in the Ext JS space.
  • SASS and Compass - Technologies like Ext JS and Sencha Touch use SASS and Compass to derive the CSS which the applications ultimately use.
  • HTML5 Robot Java Support - For acceptance testing, the existing Gradle testing functionality can deal with the HTML5 Robot Java API tests as plain JUnit tests. It is recommended that you tie in Test Data Set Management so that individual tests run against the same data environment.
  • HTML5 Robot Gwen Support - For acceptance testing, Gradle support for the Gwen command-line tools in order to run Gwen tests directly from the build.

See http://framework.appfoundation.com/index.php?title=AF_Gradle for more information about usage and examples.

Saturday, November 23, 2013

HTML5 Robot 1.1 Released

HTML5 Robot 1.1 can be downloaded from this location: http://html5robot.com/downloads/

Java Changes

  • XPathUtils.findExtJsFileFieldByDefault(): Returns the XPath for getting an Ext JS File field assuming there is only one in the page
  • XPathUtils.findExtJsFileFieldByDefaultInDiv(String divId): Returns the XPath for getting an Ext JS field field inside the the given assuming there is only one
  • XPathUtils.findExtJsFileFieldByOccurrence(int index): Returns the XPath for getting an Ext JS field field by its occurrence within the page
  • XPathUtils.findExtJsFileFieldByOccurrenceInDiv(int index, String divId): Returns the XPath for getting an Ext JS field field by its occurrence within the given div
  • XPathUtils.findInputByClass(String name): Returns the input that has the class of the given value
  • XPathUtils.findInputByClassInDiv(String name, String divId): Returns the XPath for the input that has the given class in the given div
  • XPathUtils.findButtonByClass(String name): Returns the XPath for the button of the given class
  • XPathUtils.findButtonByClassInDiv(String name, String divId): Returns the XPath for the button of the given class inside the given div
  • XPathUtils.findButtonByTextOccurrence(int index, String text): Generates the XPath for getting the button with the given text’s occurrence based on the given index. For example: I want the second occurrence of the button with the text of OK.
  • waitUntilElementDoesNotExist(WebDriver driver, By by, int waitSeconds, int retries) changed to waitUntilElementDoesNotExist(WebDriver driver, By by, int timeout), (works faster now) and made to attempt every second until the timeout is reached. The old logic waited every total timeout for 2 times, which was not needed and too long.
  • waitUntilElementExists(WebDriver driver, By by, int waitSeconds, int retries) changed to waitUntilElementExists(WebDriver driver, By by, int timeout), (works faster now) and made to attempt every second until the timeout is reached. The old logic waited every total timeout for 2 times, which was not needed and too long.
  • Form4TestBase now works for Firefox, Internet Explorer, and Chrome instead of just Chrome. You don’t need to use a file detector, just sendKeys to the file input element.

Gwen Changes

  • Browsers now expand to fill the screen when the test starts
  • Added web element type of extjsfilefield, which is used for interacting with the file input fields on pages used for upload
    • extjsfilefield by text “foo”, Gets the file field associated with the button with the text “foo”
    • extjsfilefield by text “bar//foo”, Gets the file field associated with the button with the text “foo” in the div “bar”
    • extjsfilefield by occurrence “2″, Gets the second occurring file field in the page
    • extjsfilefield by occurrence “bar//2″, Gets the second occurring file field within the “bar” div
    • extjsfilefield by default method, Gets the file field assuming there is only one
    • extjsfilefield by default “bar//”, Gets the file field in the “bar” div
  • You set the file like the following: type “C:\\some\\path\\file.txt” into extjsfilefield by occurrence “2″
  • Added the locator expression type of “by class” to the following web elements, which matches against the CSS class attribute value:
    • input by class “foo”, Gets the input with the CSS class attribute of “foo”
    • input by class “bar//foo”, Gets the input with the CSS class attribute of “foo” in the div of “bar”
    • button by class “foo”, Gets the button with the CSS class attribute of “foo”
    • button by class “bar//foo”, Gets the button with the CSS class attribute of “foo” in the div of “bar”
  • Added web element type of extjspanel which is used for interacting with Ext JS panels, particularly when they are collapsible in which you need to click on them.
    • extjspanel by text “Some Text”, Gets the Ext JS panel with the header text of “Some Text”
    • extjspanel by text “bar//Some Text”, Gets the Ext JS panel with the header text of “Some Text” in the div of “bar”
  • Added web element support to the button for “by occurrence“. This was done because there are a lot of cases when you are dealing with several buttons all with the same text in a single page.
    • button by occurrence “2//New”, Gets the second occurrence of the button with the text of “New”
  • wait until element gone, (works faster now) now waits for the max time specified in the timeout and runs checked every second instead of every default timeout unit of time for 2 times.
  • wait until element exists, (works faster now) now waits for the max time specified in the timeout and runs checked every second instead of every default timeout unit of time for 2 times.
  • type “path” into extjsfilefield by text “Bar” now works for Firefox, Internet Explorer, and Chrome instead of just Chrome


Tuesday, November 5, 2013

HTML5/Sencha/Ext JS Web Browser Automation

I have spent the last couple of years working heavily with Sencha Touch/Ext JS, and ran into a lot of issues when it came to writing test automation suites that run in web browsers. It is for this reason I created HTML5 Robot, which makes writing these tests easy. 

HTML5 Robot is based on a series of best practices for how to reliably lookup and interact with components based on attributes and conditions which are not dynamic. It then provides shortcuts for doing this with all of the HTML, Ext JS, and Sencha Touch components that you would need to interact with. It comes in 2 flavors: 

  1. Java - Familiar Selenium and JUnit based API that has built in web driver support for all modern browsers. 
  2. Gwen - A human style language for quickly and easily creating and maintaining browser tests, which comes with its own integrated development environment. All of which is based on the Java API. 
For example if you were wanting to click the "OK" button in an Ext JS dialog, you could do the following in Java: 

    click(findExtJsMessageBoxButtonByText("OK")); 

...and you could do the following in Gwen: 

    click extjsdialogbutton by id "OK" 

It includes extensive documentation in both Java and Gwen, outputs JUnit and its own HTML-style reports, and integrates with any build and continuous integration tool such as Ant, Gradle, and Jenkins. 

You can download the entire thing for free and check it out. Let me know if you have any questions.

Contributors