Table of Contents

Project Setup

Project Creation

Project Structure

Jars and Drivers

Configuring Build.gradle and GebConfig.groovy

Function of other directories

Spock

Spock tests, or feature methods, are located in the specification directory of the project. The test spec class must extend Specification or GebSpec. Feature methods are named with String literals. A feature method must have at least one block. These blocks consist of given, when, then, expect and cleanup.

Spock Feature Methods

As stated previously a feature method must contain at least one block. While there are 5 blocks to choose from in practice only 2 are really necessary; when and then.

Spock Fixture Methods

Like JUnit Spock provides fixture methods for setting up and cleaning up before each test or class.

Spock Extensions

Spock also provides extensions to the feature methods by use of annotation.

GEB

Geb locates page content by use of a JQuery like syntax.

        1. $('input')                           - returns all input elements on the page
        2. $('div', 0)                          - returns the first div element
        3. $('div', id: 'someDiv')              - returns the div with matching id
        4. $('div.someClass')                   - returns div/divs with class equal to 'someClass'
        5. $('div', 1, title: 'someDiv';)       - returns div with title 'someDiv' at index 1
        6. $('td', text:'My data')              - returns td or tds with text matching 'My data'
        7. $('td', text:contains('My data'))    - returns td or tds whose text contains 'My data'
        

NAVIGATOR ISSUES

Some elements can prove more difficult to access than others:

Geb provides some more JQuery like syntax to get around some of these instances.

        $('th', text:'Some Heading').parent('table').find('tbody')[0].find('tr').text() - will return all table rows text of the first tbody element in the table with heading 'Some Heading'
        
        $("table", class: "gwt-TabLayoutPanelContent").find("td", text:"Select check").previous("td").find("input") - accesses the checkbox in the table located before the td with text 'Select check'
        

Occasionally attempting to access the text of an element will return null when the text is clearly visible in the GUI. In some cases the value() method can resolve this.

        $('input', id:'name').value()

In cases where this does not succeed, if the text to be verified is already known we can access the browsers 'find' functionality and copy the highlighted text from the screen.

        
        //Using Sikuli to open the browsers 'find' search box and type to it 
        screen.keyDown(Key.CMD + "f")
        screen.keyUp(Key.CMD + "f")
        screen.type('Text I wish to validate')
        
        //Using java robot to copy text to system clipboard and store returned value in string
        Robot r = new Robot()
        r.keyPress(KeyEvent.VK_META)
        sleep(200)
        r.keyPress(KeyEvent.VK_C)
        sleep(200)
        r.keyRelease(KeyEvent.VK_C)
        sleep(200)
        r.keyRelease(KeyEvent.VK_META)
        sleep(2000)
        String getTextForValidation = (String) Toolkit.getDefaultToolkit().getSystemClipboard().getData(DataFlavor.stringFlavor)
        
        

Pages

Geb Pages are used to provide the url, an 'at' checker to verify the page and a content closure to model elements for interaction.

As seen above elements are defined using navigators within the content closure. It is possible to prefix the defining closure with '(wait:true)' as seen in certain cases. This invokes the GebConfig.groovy waiting presets.

WAITING ISSUES In some edge cases this '(wait:true)' prefix may fail to handle an element in the way you would imagine. Returning from another page and attempting to immediately access the element may result in an error, or similar results may be seen while dealing with a popup dialogue. In these cases where a prefixed element is still failing to be acquired or clicked it is necessary to directly invoke the waiting clause with the 'waitFor{someElement.click()}' closure directly in the test.

Modules

Modules provide a means of encapsulating data that is repeated or common across multiple pages. A Module is is defined as in the class below.

It is then included in the page content with the following syntax.

     profile {module MyProfileModule}
     

Elements of the Modules content are then accessible with a chaining syntax.

     profile.firstName = 'MyUsersFirstName'
     

Spec

The spec directory contains the test classes. Each test sheet written for the application comprises one test class and is named with the name of the test sheet followed by the word spec in-line with convention , eg, TestUserSpec.

Once the developer declares which page they are at in the code they can then refer to the content within that pages closure.

SharedResources

This directory is used for logic which will be required throughout all test classes such as log in methods, user setup, fields for validation etc.

Sikuli

Image Setup

Following the inclusion of Sikuli the ImageSetup class has been added to the SharedResources directory. Here the Sikuli Screen is instantiated and image files stored in the resources/images directory are instantiated in the form of Sikuli Patterns for use in validation or application interaction throughout the test classes.

Using Sikuli

With the Screen instantiated in the ImageSetup you can can use sikuli to verify or interact with the GUI. The sikuli screen constructor can take an int argument specifying which screen in an extended display you wish it to work on, ex, Screen.s = new Screen(1). While this can be convenient while developing it has shown some inconsistencies. For this reason it is better that tests are carried out with only one active monitor.

   //using sikuli to verify, click and locate objects
   screen.find(someImg)       - fails if not found
   screen.exists(someImg)     - returns a boolean
   screen.findAll(someImg)    - iterator of all matches found
   screen.click(someImg)      - clicks image
   screen.doubleClick(someImg)- double click
   

Sikuli searches with a default similarity of 70% or 0.7. While this is suitable for most images in some cases the similarity required may be lower or higher depending on needs. This can be achieved with the similar method.

   //lowering similarity to catch all near matches
   screen.findAll(someImg.similar((float) 0.6))
   
   //raising similarity to 95% to eliminate any near matches
   screen.click(someImg.similar((float) 0.95))  
   
   //selecting a point other than center of found image
   screen.click(someImg.targetOffset(20,15)) 
   
   

Overall Issues

Stale Element Exception

Known Cause This is usually caused by attempting to access an element contained within a popup or some content which was not previously visible.

Solution Invoking waitFor{} closure on the action in the code producing the error.

Element not clickable at point

Known Cause This is usually caused by moving from a new page back to an old one and attempting to access an element.

Solution Invoking waitFor{} closure on the action in the code producing the error.

Wait Timeout

This can be caused by inaccurate arguments provided to the waitFor closure such as navigator selection, an image not present etc.

Required Data for Test Execution

In the case of the NocPortalGebTestingProject some data is presumed to exist before testing.