Beruflich Dokumente
Kultur Dokumente
This chapter will provide you with a basic understanding of XPath. Just enough to cover the basic
requirements for writing Selenium tests.
XPath is the XML Path Language. Since all HTML, once loaded into a browser, becomes well
structured and can be viewed as an XML tree, we can use XPath to traverse it.
I'll include the listing of the XHTML for the basic_web_page.html here so you can follow along:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html>
<head>
<title>Basic Web Page Title</title>
</head>
<body>
<p id="para1" class="main">A paragraph of text</p>
<p id="para2" class="sub">Another paragraph of text</p>
</body>
</html>
XPath Expressions
XPath expressions select 'nodes' or 'node-sets' from an XML document.
e.g. The XPath expression //p would select the following node-set from the example in the Basic
HTML Theory section:
Node Types
XPath has different types of nodes. In the example XHTML these are:
Document node (the root of the XML tree): <html>
Element node e.g.:
<head><title>Basic Web Page Title</title></head>
Selections
/
start selection from the document node
allows you to create 'absolute' path expressions
e.g. /html/body/p matches all the paragraph element nodes
assertEquals(2,selenium.getXpathCount("/html/body/p"));
//
start selection matching anywhere in the document
allows you to create 'relative' path expressions
e.g.
//p matches all paragraph element nodes
assertEquals(2,selenium.getXpathCount("//p"));
@
selects attribute elements
e.g. //@id would select all the attribute nodes
assertEquals(2,selenium.getXpathCount("//@id"));
Predicates
Predicates help make selections more specific and are put in square brackets.
Predicates can be indexes. e.g.
//p[2] selects the second p element node in the node-set,
assertEquals("Another paragraph of text",selenium.getText("//p[2]"));
//p[@class='main'] selects the p element node where the value of the attribute class is 'main'
assertEquals("A paragraph of text", selenium.getText("//p[@class='main']"));
Advanced
XPath is a full programming language so you can perform calculations (e.g. last()-1), and use
boolean operations ( e.g. or, and)
//node()
get all the nodes (try it, you may not get the results you expect)
//body/node()
get all the nodes in the body (again, try it to see if you get the value you expect)
* matches anything depending on its position
@* matches any attribute
e.g. //p[@*='para1'] would match the first paragraph
assertEquals(1,selenium.getXpathCount("//p[@*='para1']"));
assertEquals(2,selenium.getXpathCount("/html/*"));
//*[starts-with(.,'Basic')]
would match any node where the contents of that node start with 'Basic', in our
Boolean Operators
//*[starts-with(@id,'p')]
find all paragraphs where the id starts with 'para' and the text contains 'Another' i.e. the
would
match any node where the id name started with 'p', in our example this
second
paragraph/
would match the paragraphs
assertEquals("Another paragraph of text",
selenium.getText(
assertEquals(2,
"//p[starts-with(@id,'para') and contains(.,'Another')]"));
selenium.getXpathCount("//*[starts-with(@id,'p')]"));
//*[@id='para1'
@id='para2']
There
are many XPathorfunctions
available to you, I have just picked a few of the most common
ones thatfind
I use.
I recommend
you
some
of id
theisweb
sitesi.e.
below
to learn
more about XPath
any
node where that
the id
is visit
'para1'
or the
'para2'
our two
paragraphs
functions, and experiment with them.
assertEquals(2,
selenium.getXpathCount("//*[@id='para1'
Recommended web sites
for function references: or @id='para2']"));
http://www.w3schools.com/XPath/xpath_functions.asp
XPath
Functions
http://msdn.microsoft.com/en-us/library/ms256115.aspx
Since XPath is actually a programming language it has built in functions which we can use in our
statements.
http://www.xmlpitstop.com/ListTutorials/DispContentType/XPath/PageNumber/1.aspx
XPath
Some common XPath functions are listed below
contains()
XPath optimisation
allows you to match the value of attributes and elements based on text anywhere in the
For our testing
we typically
want to get the shortest and least brittle XPath statement to identify
comparison
item
elements on a page.
e.g.
Some XPath optimisation strategies that I have used are:
//p[contains(.,'text')]
use the id,
would match any paragraph with text in the main paragraph e.g. Both our
use a combination
of attributes to make the XPath more specific,
paragraphs
start at the first
unique element
assertEquals(2,
selenium.getXpathCount("//p[contains(.,'text')]"));
We have to make a trade off between handling change and false positives. So we want the XPath to
//p[contains(.,'Another')]
return the correct item, but don't want the test to break when simple changes are made to the
would match any paragraph with Another in the paragraph text, in our
application undertest.
example this would match the second paragraph.
Use the ID
If the element//p[contains(@id,'1')]
has a known id then use that e.g.
//*[@id='para2']
would match any paragraph where the id had '1' in it, in our example this is the
paragraph
Or you probably wantfirst
to be
even more specific and state the type e.g.
//p[@id='para2']
assertEquals("A paragraph of text",
selenium.getText("//p[contains(@id,'1')]"));
starts-with()
This Firebug plugin adds a few additional abilities to Firefox. By right clicking on an element in a
page in Firefox, you now have the ability to Firefind Element.
You can also use the CSS statement in the getAttribute statement to get specific attributes from
elements e.g.
assertEquals("para2", selenium.getAttribute("css=p.main@id"));
Selections
CSS selectors, use a hierarchical definition much like XPath to match elements on the page.
p[class='main']
selects the p element where the value of the class attribute is 'main'
assertEquals("A paragraph of text",
selenium.getText("css=p[class='main']"));
p[id]
select all p elements with an id attribute
although this matches more than one element, Selenium will always use the first
assertEquals("A paragraph of text",
selenium.getText("css=p[id]"));
Indexed Matching
CSS Selectors also supports Indexed matching. The w3c specification lists all the indexing
predicates, these are called pseudo classes in the w3c specification e.g.
nth-last-child() , matches the nth child of an element counting backwards from the last
child
body p:nth-last-child(1), returns the last child for the body element
assertEquals("Another paragraph of text",
selenium.getText("css=body p:nth-last-child(1)"));
nd
The Selenium documentation describes support for all css1, css2 and css3 selectors. With the
following exceptions, so no support yet for:
CSS3 Name spaces,
the following pseudo classes(:nth-of-type, :nth-last-of-type, :first-of-type, :last-of-type,
:only-of-type, :visited, :hover, :active, :focus, :indeterminate)
Also no support for the pseudo elements(::first-line, ::first-letter, ::selection, ::before, ::after).
Advanced
Combining Matches
You can combine several selections by chaining them in a comma separated list, the items will be
returned the order listed e.g.
p , title
get any paragraph element and the title element
assertEquals("A paragraph of text",selenium.getText("css=p, title"));
assertEquals("Basic Web Page Title",selenium.getText("css=title, p"));
Boolean Operators
You can setup matches with multiple conditions e.g.
p[class='main'][id='para1']
p:not([class='main'])[id^='para']:not([class='sub'])
you can have multiple negations in the selector
would match any paragraph which does not have the class main and the id starts
with para and does not have the class sub - in our example this would match no
elements
assertEquals(0,
getCSSCount("p:not([class='main'])[id^='para']:not([class='sub'])"));
Useful Links
http://kimblim.dk/css-tests/selectors/
A page that lists browser compatibility with various CSS selectors.
http://robertnyman.com/firefinder/
Homepage for Firefinder with links to the support google group and instructions on its
use.
http://www.w3.org/TR/css3-selectors/
The official W3C selectors specification
The W3c specification, has an excellent summary of the CSS selection patterns