GDAP Project specific TestNG - Selenium - Java
20131120 dumped from Word Doc
GDAP Selenium Implementation 1
Selenium Locators 1
Page Objects 2
GDAPCommon utility class 3
IFrames used for TinyMCE rich text editor 3
How did I get to here re methodology: 5
Selenium IDE vs driven by a programming language 5
Issues re principles: 5
Why no PageFactory? 6
Locators mapping in page objects 6
Specific PageObject notes/oddities 7
Common: 7
PageCommon 7
PageItemGroup (Collection of classes) 7
PageItemGroup_Header 7
PageItemGroup_Items 7
PageItemGroup_Workbench 8
PageJob_List 8
PageJob_Selected 9
PageLogin 9
PageMoveEntity 9
GDAP Selenium Implementation
Prerequisites
- Eclipse Java EE edition
- Selenium Java Client
- Selenium Server Standalone
Selenium Locators
Selenium finds elements ‘by’ a locator string & type
A locator string & type can be resolved to an instance of the By class:
By elementByLocator = By.id(“username”);
By elementByLocator = By.xpath(“li[contains(@class,'selected')]/child:: a[span[.='Jobs']]”);
A By object can be passed into various Selenium functions for actions/asserts
return driver.findElement(by).getText();
Page Objects
Introduction
Each application page (or logically separate functional part of a page) is a Java class modelled on the Page Object concept.
Page Objects are intended to map Application pages to make them accessible to tests
- Each is it’s own class
- Provide a self contained testing interface to a part of the application by providing (and abstracting):
- locators to make elements on the application page accessible to tests
- services as available to a user
- services always self assert where possible, (i.e. create job action asserts job was created)
- Where a service moves to another PageObject, returns that PageObject to model the flow between pages. (In the event the new PageObject constructor fails this also allows us to trace where it was created from)
- Reduces maintenance in the event a service or locator changes
Page Object layout
Within each Page Object class we have fairly consistent sections
- Constructor:
- Always calls own assertCommonElements method to verify are on the expected page
- Location mapping
- maps all elements on the page that require interaction
- always return Selenium ‘By’ object
- can be:
- Static (fixed)
- Dynamic (a method that accepts a parameter, ie Job State ‘In Draft’)
- Named as byXxxxxx to indicate is a By object
- *** Document SINGLEELEMENT enum mechanism here ***
- *** Document dynamic selectors here (ie row by title.no, pagination by page no etc) ***
- Query state
- Methods to query the state of the page i.e. doesTitleExist
- Use by page Object actions (below) or directly in test cases (Violation of test encapsulation here?)
- Asserts
- Methods that performed canned asserts to check elements on locators
- Can take parameters to pass through to dynamic locators
- assertCommonElements must exist for use by the page object constructor
- If an assert fails the test fails
- Actions:
- Methods that represent a user interaction (service) on the page
- Method name should reflect the action
- If an action results in moving to another page or opens another functional area as mapped by a different page object, returns the new page object representing the new page
- Where possible if an action performs any type of page change (display / update / create application entity (i.e. job) where possible it should also self assert the change.
GDAPCommon utility class
Hold common functionality:
- Constants
- Enums for parameters, (eg Job states, user roles)
- Enums for picklists
- TestNG specific functionality
- Start / Stop browser & application
- Logging to test Output utilities
- Assert ‘waitFor’ helpers
- Methods for querying state of elements (e.g. isElementPresent, getElementText)
- Element actions (eg click, clearAndEnterText)
IFrames used for TinyMCE rich text editor
- Each richtext field exists as a hidden textarea tag (escaped from what I can see)
- Associated with each per above is an IFrame containing TinyMCE editor, uses above as both source & target
What does the user interact with?
So to verify the content we need to read from the IFrame & to input data, we need to type into the IFrame editor
To access elements within IFrames from Selenium requires the Selenium focus to switch to the target IFrame before performing the action
- Use driver.switchTo.frame(locator)
- Use driver.switchTo().defaultContent() to get back to top of DOM
How did I get to here re methodology:
Selenium IDE vs driven by a programming language
IDE initially:
Started with the IDE, spent a fair amount of time mapping locators into user-extensions.js then started building scripts before quickly running into issues:
- Readability: scripts very difficult to just look at
- Abstraction/encapsulation: difficult & clunky to modularise test functions & pass variables
- Extensibility: limited
- Maintainability: difficult for all the above
- Conditional testing: used flow extension but just more messy scripts
WebDriver & Java:
Why Java:
- Widest user base
- Easy to pickup for non java programmers
- Eclipse quick setup with Selenium / TestNG
- Solves a lot of the issues re Selenium IDE above
Issues re principles:
Locators: private or public?
http://code.google.com/p/selenium/wiki/PageObjects says:
- The public methods represent the services that the page offers
- Try not to expose the internals of the page
BUT: all examples show direct use of locators for asserts, seems to invalidate the above
Page actions: self verify or not?
http://code.google.com/p/selenium/wiki/PageObjects says:
Generally don't make assertions
BUT: for encapsulation and reuse & ease of maintenance, I prefer to have every action where possible self assert
- Pro: Cuts down on test complexity & makes them quicker to create & maintain
- Con: means PageObject action methods must be robust & checked for completeness
Why no PageFactory?
Tried using PageFactory initially, but in the end determined that support for it is half baked. PageFactory works well for pages where each element has a unique ID as it will then dynamically allow calling of WebElements without requiring explicit declaration. But we have complex pages with dta grids etc where ID’s are not possible.
PageFactory locators are of type WebElement / WebElements but most selenium functions accept By objects as locators.
Additionally, when Selenium resolves a WebElement to a actual page element it always expects the WebElement to exist, so custom code is required to simply determine if a WebElement exists on the page to handle the exception.
There were other issues as well…
Locators mapping in page objects
Still experimenting to find best patterns, use Enums where possible for XPath fragments to cut down on coding
Specific PageObject notes/oddities
Common:
User display names not modelled, assumes is same as userID
Need to cleanup on test fail, ie log out user
Need to take screenie on test fail & append to test log
PageCommon
Notes
None
Incomplete modelling:
- No roles rights modelling for asserts
PageItemGroup (Collection of classes)
- Marlena is coming to review usability. I suggest there will be changes in this space
PageItemGroup_Header
Notes
Xpath is more or less ok with minor annoyances not worth developer time:
- Toolbar buttons we look at label text
- Item counts are positional
Incomplete modelling
None
PageItemGroup_Items
Notes
Xpath is complex:
- Grid cell identifiers used in multiple ways, ie target for selecting row as well as specifying target elment but ok
- Hoping for commonality between grid expanded item detail view & workbench view
With items scrolling out of view suggest be careful choosing between ElementIsPresent & ElementIsVisible
Item Grid issues:
- Grid columns currently available are just a subset and is not to be built for a while (AndrewS)
- AndrewS suggest that if we are time pressured the Grid expanded view will be dropped
- Locators:
- Grid detail: not all expected fields are there yet.. need to eventually compare with future use case re editing items to ensure full set of fields
- How to manage available fields by item type?
- Inter item relationships
- AndrewS suggests workbench is pretty much fully populated
- No read only view yet, no idea how much reuse of locators between edit view & read only view
- Alternative Title is expected to be Rich text but is not
- Rich text fields are in iFrames so need special handing
- Need to allow for fields available by item type
Incomplete modelling
PageItemGroup_Workbench
Notes
Incomplete modelling:
- Modelling on fields as currently delivered, need to model against requirements once finalised for all 3 item types (if we still have 3 item types by then)
- Only models the left list portion, refer PageJob_Selected for remainder
- A job header by state only exists if there are relevant jobs for the current user
- Job rows are always present even if job list header by state is not selected
- Need to be careful as we can expand/collapse a job list and leave a selected job element hidden from the users view…
- In modelling user behaviour, we must always make the list of jobs we are targeting visible before interacting with it including asserts
- createJobAndVerify: Job type has no default and is currently not mandatory on new job creation, however, it is mandatory in UC201 Job creation during clone item..
- Models selected job portion of Jobs page
- Entities list locators & interaction
- Job history entries
- Comments
- Create Entity allows a click on the arrow element separately from the dropdown label, only using the arrow for now
PageJob_List
Notes
Incomplete modelling:
PageJob_Selected
Notes
Incomplete modelling:
PageLogin
Notes
None
Incomplete modelling:
- Need to login as different rights & check availability of relevant default options
- Consider: user can have mixed roles
PageMoveEntity
Notes
Incomplete modelling:
TBD
xx