xirkus / shelob

A meta-framework that provides Page and Element Objects over WebDriver 2.x

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

/**
	Copyright (c) 2011, Strata Health Solutions Inc.
 	All rights reserved.

	Redistribution and use in source and binary forms, with or without modification, are permitted 
	provided that the following conditions are met:

	Redistributions of source code must retain the above copyright notice, this list of conditions 
	and the following disclaimer.

	Redistributions in binary form must reproduce the above copyright notice, this list of conditions 
	and the following disclaimer in the documentation and/or other materials provided with the distribution.

	THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED 
	WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 
	A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 
	FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 
	BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 
	OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 
	OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, 
	EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
**/

This framework has been released under the BSD License by Strata Health Solutions. For more information regarding
the license please visit http://www.opensource.org/licenses/bsd-license.php .

/\(00)/\

== Framework Objectives ==

WebDriver automation primarily consists of finding DOM objects to be manipulated by the tests. While most WebDriver examples include finding test objects as part of the test, this is not ideal as it does not encourage reuse of UI components that are uniformly used throughout an application. This situation can somewhat be mitigated by the use of the WebDriver PageFactory / Page object pattern which aggregates objects into container Page classes, but requires and explicit instance of an object to resolve. However, this method is not applicable to dynamically generated applications whose objects can change dramatically between client interactions. As well, it is inefficient to require explicit definitions of every single object that will participate in a test regardless of whether it is used or not. The proposed solution merges the idea of the Page Object pattern with a feature present in Selenium 1, but not in Selenium 2 - UI mapping. This UI map is represented in the form of Element classes that represent lookup strategies for resolving DOM locators for reusable UI objects. This allows for both explicit Element mappings as well as templated mappings which can be resolved dynamically via parameterization. For example, instead of having to explicitly define all visible <span> elements we want to test for, we can specify a single span template which will allow us to resolve all possible spans via a parameter. This approach has the following benefits:

1. Using templates allows Page / Element configuration to be simplified.
2. Separating out Element configuration isolates tests from changes to the underlying application.
3. Elements can be unit tested to ensure consistent resolution of DOM objects.
4. Elements can be combined compositionally to model Elements with richer behaviors.
5. Templates allow similar Elements to be resolved via different lookup strategies.
6. By combining Elements with Pages, we can create a graph of application flow which we can use to model client navigational transitions.

Using a framework which supports these features divides the process of test automation in two distinct components - configuration and test creation.

The Shelob meta-framework provides the structure to compose the Element and Page graph which represents the automatable components of a web application. Pages are localized application context constructed from simple POJOs, each of which include a dictionary of Elements that can be referenced within that context. By using the same visual qualifiers to identify Elements as presented in the application, test writers need not concern themselves about the underlying lookup strategy. As long as the Element is resolvable and accessible via automation within the Page context, then it can be used as part of the test. This improves the readability of generated tests - they function both as executable code as well as documentation for expected application behavior.

== Configuration ==

=== Elements ===

The whole purpose of configuration is to take the cost of resolving automatable components upfront as opposed to each time for every single test. In this regard, WebDriver provides the following lookup strategies:

- By Class Name (Unfortunately, this seems to do literal string comparisons on the class attribute; it does not seem to be able to resolve Elements using partial class attributes)
- By CSS Selector (limited form of Xpath)
- By Id (Assuming that the object id is unique across the DOM, this is the most succinct identifier and highly preferable for selecting unique objects)
- By Link Text
- By Name (Uses the name attribute; like id, this is useful when it is also unique across the DOM. For grouped selection items such as radio buttons, this attribute may not be unique)
- By Partial Link Text
- By Tag Name
- By Xpath (The most flexible)

==== The Preferred Lookup Strategy - By ID ====

The html specification of the DOM stipulates that the id attribute should be unique within a DOM. When possible, using ids are preferable as they succinctly identify a particular object. In addition, changes to the DOM have no effect when attempting to resolve an object via this strategy.

While this is useful for most objects, it is sometimes impractical to generate a unique id for every rendered object in the DOM. In addition, dynamic applications sometimes render synthetic id's which may not be reproducible between instances and/or invocations of an application. The limitations of ids are particularly noticeable in table objects with cells arranged in columns and rows. Identifying a specific cell usually requires contextual information such as the column and/or row header information to determine the correct object. Another example is when <input> objects of type "text" are usually associated with labels (usually a div/span/td objects) from the perspective of the user. It is sometimes useful (or necessary when no other element attribute can be used to disambiguate similar elements) to use the visual qualifier as a means of locating the target object.

In these cases where object disambiguation is relative to its context, the Xpath strategy is particularly useful.

==== The Swiss Army Knife of Strategies - By Xpath ====

Every other lookup strategy can be encoded using Xpath; in this sense, Xpath is the most expressive. This ability however comes with at the cost of performance. In addition, changes to the DOM can directly affect Xpath expressions. Ideally, Xpath object resolution is used as a last resort when other strategies are inadequate to locate an object within the DOM or when it is useful to create a single expression to resolve similar objects of a given pattern using an expression template. In this sense, Xpath is the regex of the DOM.

Xpath expressions become more important when constructing composite Elements. The ability to construct parent/child relationships allows individual component expressions to be resolved relative to another Element.

==== The Alternatives ====

The governing principle in object identification is uniqueness. If the other lookup strategies can guarantee no duplicates, then they should be used. For instance, the name attribute when used to store a user preference identifier can also be useful in identifying objects succinctly.

=== Pages ===

Pages serve as dictionaries for Elements that are associated with it's context. Configuration consists of specify Elements and their dictionary keys. Since each Page encapsulates its context, the same Element key can be used in different contexts. For example, the "Add" button in one context may illicit a different response in another context. As part of specifying Elements, Page objects are also responsible for wiring triggering Elements to navigational or Page transitions. An Element associated with a transition can have a navigational method invoked upon it and return and instance of the new Page context. Through this mechanism, an application graph can be constructed. The relationship between different Pages is not directly between Page object themselves, but through the intermediary Elements which can invoke transitions. This allows transitions away from the current Page context to be expressed as well as transitions that affect a sub-context within a Page.

By using namespace to structure Page hierarchies, we can accomodate Page objects with duplicate names but with different functional contexts. This also allows shared components to be reused throughout the application.

==== Re-editable and Reusable ====
Configuration becomes a process of binding the application to a test harness which is decoupled from executable test cases. Application changes at either the Element or Page level can be localized. This minimizes the impact on test cases which depend on these abstractions. In addition, duplication in Pages and Elements is substantially reduced resulting in a test harness that can evolve with the changing requirements of the Application Under Test (AUT).

TODO : Update examples to point to a live site.
TODO : Include usage documentation.

About

A meta-framework that provides Page and Element Objects over WebDriver 2.x


Languages

Language:Java 100.0%