You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: docs/guides/selectors.md
+63-56Lines changed: 63 additions & 56 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -1,129 +1,136 @@
1
-
# How To Write Good Selectors
1
+
# How To write good selectors
2
2
3
-
Selectors are an atomic unit of test writing. They fit into the hierarchy like this: MFTF tests make use of action groups, which are made up of actions, which interact with page objects, which contain elements, which are specified by selectors. Because they are the building blocks, we must take care when writing them.
3
+
Selectors are the atomic unit of test writing. They fit into the hierarchy like this: MFTF tests make use of action groups > which are made up of actions > which interact with page objects > which contain elements > which are specified by selectors. Because they are fundamental building blocks, we must take care when writing them.
4
4
5
5
## What is a selector?
6
6
7
-
A "selector" is like an address to an element in the Document Object Model (DOM). It locates those elements and allows MFTF to interact with them. By element we mean things such as input fields, buttons, tables, divs, etc. By interact we mean actions such as click, fill field, etc.
7
+
A "selector" works like an address to an element in the Document Object Model (DOM). It specifies page elements and allows MFTF to interact with them.
8
+
By 'element' we mean things such as input fields, buttons, tables, divs, etc.
9
+
By 'interact' we mean actions such as click, fill field, etc.
8
10
9
11
Selectors live inside of MFTF page objects and are meant to be highly re-usable amongst all tests. They can be written in either CSS or XPath.
10
12
11
13
## Why are good selectors important?
12
14
13
-
Good selectors are important because they are the most re-used component of functional testing. They are the lowest building blocks of tests, the foundation. If they are unstable then everything else built on top of them will inherit that instability.
15
+
Good selectors are important because they are the most re-used component of functional testing. They are the lowest building blocks of tests; the foundation. If they are unstable then everything else built on top of them will inherit that instability.
14
16
15
17
## How do I write good selectors?
16
18
17
-
We could cover this subject with an infinite amount of documentation and some lessons only come from experience. But this guide will explain some DOs and DONTs to help you along the way towards mastery.
19
+
We could cover this subject with an infinite amount of documentation and some lessons only come from experience. This guide explains some DOs and DONTs to help you along the way towards selector mastery.
18
20
19
21
### Inspecting the DOM
20
22
21
-
To write a selector you need to be able to see the DOM and find the element within it. Fortunately you don't have to look at the entire DOM every time. Nor do you have to read it from top to bottom. Instead you can make use of your browsers builtin developer tools or go a step further and try out some popular browser extensions.
23
+
To write a selector you need to be able to see the DOM and find the element within it. Fortunately you do not have to look at the entire DOM every time. Nor do you have to read it from top to bottom. Instead you can make use of your browsers built-in developer tools or go a step further and try out some popular browser extensions.
22
24
23
25
See these links for more information about built-in browser developer tools:
See these links for common browser addons that may offer advantages over browser developer tools:
28
-
*[Live editor for CSS, Less & Sass - Magic CSS](https://chrome.google.com/webstore/detail/live-editor-for-css-less/ifhikkcafabcgolfjegfcgloomalapol?hl=en)
*[Live editor for CSS, Less & Sass - Magic CSS](https://chrome.google.com/webstore/detail/live-editor-for-css-less/ifhikkcafabcgolfjegfcgloomalapol?hl=en)
There are many similarities and many differences between CSS and XPath. It is too much to cover in this guide alone. You should search out additional material on your own. In general:
37
+
There are similarities and differences between CSS and XPath. Both are powerful and complex in ways that are outside of the scope of this document.
38
+
In general:
34
39
35
-
* CSS is more stable, easier to read, and easier to maintain (typically).
36
-
* XPath provides several powerful tools and it has been around the longest so it’s well documented.
37
-
* XPath can be less stable and potentially unsupported by certain actions in Selenium.
40
+
*CSS is more stable, easier to read, and easier to maintain (typically).
41
+
*XPath provides several powerful tools and it has been around the longest so it is well documented.
42
+
*XPath can be less stable and potentially unsupported by certain actions in Selenium.
38
43
39
44
### Priority
40
45
41
-
The best and most simple selector will always be `#some-id-here`. If only we were so lucky to have this every time. When writing selectors, you should prioritize looking for these starting points to build your selector from.
46
+
The best and most simple selector will always be to use an element ID: `#some-id-here`. If only we were so lucky to have this every time. When writing selectors, you should prioritize looking for these starting points to build your selector from.
42
47
43
-
1. ID, Name, Class, or anything else that is unique to the element
48
+
1. ID, name, class, or anything else that is unique to the element
44
49
2. Complex CSS selectors
45
50
3. XPath selectors
46
-
4. If none of the above work for you, then the last resort is to ask a developer to add a unique ID or Class to the element you're trying to select.
51
+
4. If none of the above work for you, then the last resort is to ask a developer to add a unique ID or class to the element you are trying to select.
47
52
48
-
Important: Notice we prefer the use of CSS selectors above XPath selectors when possible.
53
+
We suggest the use of CSS selectors above XPath selectors when possible.
49
54
50
-
### Do's and Don'ts
55
+
### Do and Do not
51
56
52
-
Let's start with the Don'ts because they're more important.
57
+
There are correct ways of writing selectors and incorrect ways. These suggestions will help you write better selectors.
53
58
54
-
#### Don't #1
59
+
#### Incorrect - copy selector/xpath
55
60
56
61
DO NOT right click on an element in your browser developer tools and select "Copy selector" or "Copy XPath" and simply use that as your selector. These auto-generated selectors are prime examples of what not to do.
57
62
58
63
These are bad:
59
64
60
-
```
65
+
```css
61
66
#html-body>section>div>div>div>div
62
67
```
63
68
64
-
```
69
+
```xpath
65
70
//*[@id='html-body']/section/div/div/div/div
66
71
```
67
72
68
-
They both include unnecessary hierarchical details. As written, we're looking for a `div` inside of a `div` inside of a `div` inside of... you get the picture. But if an application developer adds another `div` parent tomorrow, even for stylistic reasons, then this selector will break. Furthermore, when reading it, it's not even clear what was the intended target in the first place.
73
+
Both include unnecessary hierarchical details. As written, we are looking for a `div` inside of a `div` inside of a `div` inside of... you get the picture. If an application developer adds another `div` parent tomorrow, for whatever reason, this selector will break. Furthermore, when reading it, it is not clear what the intended target is. It may also grab other elements that were not intended.
69
74
70
-
#### Don't #2
75
+
#### Do not be too general
71
76
72
-
DO NOT make your selectors too generic. If a selector is too generic, there is a high probability that it will match multiple elements on the page. Maybe not today. But probably tomorrow when the application under test changes.
77
+
DO NOT make your selectors too generic. If a selector is too generic, there is a high probability that it will match multiple elements on the page. Maybe not today, but perhaps tomorrow when the application being tested changes.
73
78
74
79
These are bad:
75
80
76
-
```
81
+
```html
77
82
input[name*='firstname']
78
83
```
79
84
80
-
The `*=` means `contains`. So the selector is saying find an input whose name contains the string "firstname". But if a future change adds a new element to the page whose name also contains "firstname", then this selector will now match two elements and that's bad.
85
+
The `*=` means `contains`. The selector is saying 'find an input whose name contains the string "firstname"'. But if a future change adds a new element to the page whose name also contains "firstname", then this selector will match two elements and that is bad.
81
86
82
-
```
87
+
```css
83
88
.add
84
89
```
85
90
86
-
Similarly here, this will match any element which contains the class `.add`. This is brittle and susceptible to breaking when new elements/styles are added to the page.
91
+
Similarly here, this will match all elements which contains the class `.add`. This is brittle and susceptible to breaking when new elements/styles are added to the page.
87
92
88
-
#### Don't #3
93
+
#### Being too specific
89
94
90
-
DO NOT make your selectors too specific either. If a selector is too specific, there is a high probability that it will break due to even minor changes to the application under test.
95
+
DO NOT make your selectors too specific either. If a selector is too specific, there is a high probability that it will break due to even minor changes to the application being tested.
This selector is too brittle. It would break very easily if an application developer does something as simple as adding a parent container for style reasons.
This is the same selector as above, but represented in XPath instead of CSS. It is brittle for the same reasons.
105
110
106
-
#### Do #1
111
+
#### Use isolation
107
112
108
113
You should think in terms of "isolation" when writing new selectors.
109
114
110
-
For example, let's say you have a login form that contains a username field, a password field, and a Sign In button. First isolate the parent element. Perhaps it's `#login-form`. Then target the child element under that parent element: `.sign-in-button` The result is `#login-form .sign-in-button`.
115
+
For example, say you have a login form that contains a username field, a password field, and a 'Sign In' button. First isolate the parent element. Perhaps it's `#login-form`. Then target the child element under that parent element: `.sign-in-button` The result is `#login-form .sign-in-button`.
111
116
112
-
Thinking like this will reduce the amount of DOM that you need to worry about.
117
+
Using isolation techniques reduces the amount of DOM that needs to be processed. This makes the selector both accurate and efficient.
113
118
114
-
#### Do #2
119
+
#### Use advanced notation
115
120
116
-
If you need to interact with the parent element but it's too generic, and the internal contents are unique then you need to:
121
+
If you need to interact with the parent element but it is too generic, and the internal contents are unique then you need to:
117
122
118
-
1. Target the unique internal contents first
119
-
2. Then jump to the parent element using `::parent`
123
+
1. Target the unique internal contents first.
124
+
1. Then jump to the parent element using `::parent`.
120
125
121
-
For example let's imagine you want to find a table row that contains the string "Jerry Seinfeld". You can use the following XPath selector:
126
+
Imagine you want to find a table row that contains the string "Jerry Seinfeld". You can use the following XPath selector:
Note in this instance that CSS does not have an equivalent to `::parent`, so XPath is a better choice.
133
+
127
134
### CSS Examples
128
135
129
136
Examples of common HTML elements and the corresponding selector to find that element in the DOM:
@@ -148,7 +155,7 @@ Whitespace|Descendant Combinator|Allows you to combine 2 or more selectors.|`#id
148
155
`+`|Adjacent Sibling Combinator|Allows you to select an element THAT FOLLOWS DIRECTLY AFTER another specified element.|`#idname + .classname`
149
156
`~`|General Sibling Combinator|Allows you to select an element THAT FOLLOWS (directly or indirectly) another specified element.|`#idname ~ .classname`
150
157
151
-
Examples of CSS attribute operators and their purpose
158
+
Examples of CSS attribute operators and their purpose:
152
159
153
160
Symbol|Purpose|Example
154
161
---|---|---
@@ -157,29 +164,29 @@ Symbol|Purpose|Example
157
164
`~=`|Returns all elements that CONTAINS the given words delimited by spaces in the value.|`[attribute~='value']`
158
165
`$=`|Returns all elements that ENDS WITH the substring in the value.|`[attribute$='value']`
159
166
`^=`|Returns all elements that BEGIN EXACTLY WITH the substring in the value.|`[attribute^='value']`
160
-
`!=`|Returns all elements that either DOESN’T HAVE the given attribute or the value of the attribute is NOT EQUAL to the value.|`[attribute!='value']`
167
+
`!=`|Returns all elements that either DOES NOT HAVE the given attribute or the value of the attribute is NOT EQUAL to the value.|`[attribute!='value']`
161
168
162
169
### XPath Examples
163
170
164
171
#### `/` vs `//`
165
172
166
173
The absolute XPath selector is a single forward slash `/`. It is used to provide a direct path to the element from the root element.
167
174
168
-
WARNING: The `/` selector is brittle and should only be used sparingly.
175
+
WARNING: The `/` selector is brittle and should be used sparingly.
169
176
170
-
Here's an example of what NOT to do, but this demonstrates how the selector works:
177
+
Here is an example of what NOT to do, but this demonstrates how the selector works:
0 commit comments