1.2. Selenium/Olat Map-file aka Locator Abstraction Layer

Introduction

The start of a normal Selenium test case in OLAT could look something like this (for details refer to the Selenium in-depth chapter):

  • open http://localhost:8080/nightly/dmz

  • type <username-locator> administrator

  • type <password-locator> the_password

  • clickAndWait <login-locator>

The tricky part lies in the locators: these are generally speaking XPaths into the XHtml DOM tree.

In order to achieve the goal of having tests that survive between releases, and at the same time allow structural, graphical and internal changes that effect only the DOM tree and not complete workflows, there must be a concept of having locator URLs independent from the current XPath - i.e. we need to have a Locator Abstraction Layer

Luckily Selenium already comes with a concept called 'UI-Element'. If you have Selenium IDE installed, check here for the documentation

'UI-Element' allows defining customized locator. This means that we can define an alias locator, use that in the test and hide the implementation in a OLAT-version-specific Olat Map file. This allows tests to remain stable from release to release depending on the stability of workflows! If workflows change from release to release, then obviously tests that tested based on the old workflow need to be adjusted

Olat Map file

The Olat Map file contains a hierarchically structured list of UI-Element locators mapped to XPaths

These UI-Element locators are then used by Selenium tests and are the only locators that must be used within an Olat Selenium test (enforced by the base testclass BaseSeleneseTestCase)

The Olat map file is stored here:

$CVS/olat3ext/tests/seleniumtests/ui-map/olat-ui-map.xml

Here is an excerpt from the olat-ui-map.xml file:

		 	
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE ui-map PUBLIC "olat/ui-map" "olat-ui-map.dtd">

<ui-map>
	<pageset name="dmz" description="DMZ links">
		<xpath-ui-element name="username" xpath="//input[@id='lf_login']" description="username input field"/>
		<xpath-ui-element name="password" xpath="//input[@name='lf_pass']" description="password input field"/>
		<xpath-ui-element name="login" xpath="//input[@value='Login']" description="login button"/>
	</pageset>
	<pageset name="home" description="The home page">
		<pageset name="menu" description="the left hand menu">
			<xpath-ui-element name="settings" xpath="//div[contains(@class, 'o_home')]//div[@class='b_tree']//a[text()='Settings']" description="left navigation link 'Settings'"/>
		</pageset>
	</pageset>
</ui-map>
		 	

The above map translates into the following UI-Element locators:

ui=dmz::username()
ui=dmz::password()
ui=dmz::login()
ui=home::menu_settings()

Here is a description of the steps involved in converting the olat-ui-map.xml file into user-extensions.js

  • /olat3ext/tests/seleniumtests/build.xml triggers the whole process in target 'gen_olat-ui-map.js'

  • /olat3ext/tests/seleniumtests/ui-map/olat-ui-map.xml is the input - the actual olat ui map file

  • /olat3ext/tests/seleniumtests/ui-map/gen_olat-ui-map.xsl converts the olat-ui-map.xml into /olat3ext/tests/seleniumtests/build/classes/olat-ui-map.js

  • the three files ui-element.js, olat-ui-map.js and rollups.js are then concatenated into /olat3ext/tests/seleniumtests/build/classes/user-extensions.js which is the final user-extensions file that Selenium needs to be configured with