Advanced techniques for element positioning in introductory web automated testing

Last time I introduced the element management method based on configuration files. Next, the blogger will give a more comprehensive explanation on the advanced positioning methods of some elements. Although these advanced positioning techniques do not appear frequently in daily work, they often achieve unexpected results in some scenarios where basic positioning methods cannot be effective.

Positioning introduction

The common element positioning methods introduced in the previous issues will not be elaborated here. In fact, in the script design process of our daily web automated testing, we often encounter web pages that are damaged due to code specifications or personal habits of development students. Some attribute values ​​​​of elements in are repeated or missing. At this time, if you use common element positioning methods such as ID and CLASSNAME, you will often not be able to locate the element you want. So in this issue, we will focus on the two positioning methods of CSS Selector and XPath.

CSS Selector positioning

Although CSS Selector is also a more commonly used positioning method, its appearance rate is far lower than positioning such as ID and Class Name. As the benchmark for element positioning, our selection criteria are still the three brothers of uniqueness, readability, and maintainability. Therefore, when the ordinary positioning method fails, we will give priority to CSS Selector, and then XPath.

CSS Selector locates elements through the class, id, tag name, attribute, etc. of HTML elements. At the same time, because of its characteristics, this positioning method has high flexibility, readability, and high accuracy. In addition, precisely because of its high readability and accuracy, its execution speed is also relatively fast when executing test scripts.

1. Selector syntax

Compared with other single positioning methods, CSS Selector itself covers the following basic syntax, which is also an important foundation and basis for our later combined positioning.

  • Tag Selector - Selects elements of a specific tag type. EX:div

  • Class Selector - Selects elements with a specific class name. EX: .class (. means select class)

  • ID selector - selects elements with a specific ID. EX: #id (# means select ID)

  • Attribute Selector - Selects elements with specific attributes. EX:[attribute=value]

  • Child selector - selects the direct child elements of an element. EX: parent > child

  • Descendant selector - selects descendant elements of an element. EX: ancestor descendant

2. Combination positioning

After we have mastered all the usages of the above selectors, we can use flexible combination methods to perform high-progress element positioning in the process of designing scripts.

[Tag+Category]

For example, we can combine the two attributes of tag name and class name. Here our HTML code is:

<div class="SignFlow-tab" role="button" tabindex="0">登录</div>

We use the combination of [tag + class] to position elements:

driver.find_element(By.CSS_SELECTOR, "div.SignFlow-tab")

[Tag + Attribute]

For example, the following HTML code:

<link data-rh="true" rel="apple-touch-icon" href="https://static.xxx.com/icon-eac.png" sizes="60x60">

We use the combination of [tag + attribute] to position elements:

driver.find_element(By.CSS_SELECTOR, "link[href]")

[Class + Attribute]

For example, the following HTML code:

<input name="digits" type="number" class="Input i7cW1UcwT6ThdhTakqFm" placeholder="输入六位短信验证码" value="">

We use the combination of [class + attribute] to position elements.

What needs to be noted here is that this input element has multiple attributes. Here, three attributes are searched for the purpose of positioning as accurately as possible. If you only extract any two or more combinations, it is OK.

driver.find_element(By.CSS_SELECTOR, "input.Input.i7cW1UcwT6ThdhTakqFm[name=digits]")

[offspring + class]

The sample code is as follows:

<div class="SignFlow-tabs">
  <span class="SignFlow-tab" role="button" tabindex="0">密码登录</span>
  <span class="SignFlow-tab" role="button" tabindex="-1">短信登录</span>
</div>

We use the combination of [descendants + classes] to position elements.

What needs to be explained here is that in HTML, one element is contained by another element, which is similar to the above HTML code. The outermost div element is the parent element, and the span element is the child element. I believe this should be good. understand. The descendant selector can specify any child element in the parent element, which means that this selector can select all span child elements under the div element that have the SignFlow-tab class attribute.

In addition, whether these span sub-elements are directly used as sub-elements or are nested in deeper sub-elements, they can be specified by descendant selectors.

driver.find_element(By.CSS_SELECTOR, "div.SignFlow-tabs span.SignFlow-tab")

【Sub+Category】

The sample code is as follows:

<div class="SignFlow-tabs">
  <span class="SignFlow-tab" role="button" tabindex="0">密码登录</span>
  <span role="button" tabindex="-1">
    <span class="SignFlow-tab">短信登录</span>
  </span>
</div>

We use the combination of [sub + class] to position elements. For the descendant selector introduced earlier, the difference between the child selector and it is that the child selector will only select direct child elements, while the descendant selector can select all descendant elements. The writing also needs to be distinguished. Child selectors use ">", while descendant selectors use spaces.

driver.find_element(By.CSS_SELECTOR, "div.SignFlow-tabs > span.SignFlow-tab")

XPath positioning

1. Relative path positioning

Since we do not advocate the use of absolute paths for XPath positioning, relative paths are naturally a good solution on the other side. In the relative path positioning method, we need to specify some keywords and symbols to construct the path to achieve accurate positioning.

The following are some path positioning keywords that we often use in daily life:

  • . represents the current node, that is, the starting point of positioning

  • … represents the parent node of the current node

  • // Indicates searching for elements starting from the root node, regardless of the current node position.

  • @ represents the attribute of the element

Just saying it may be a bit abstract, so let's look at a corresponding example. The source code of a certain HTML is as follows:

<html>
    <head>
        <title>UI自动化测试平台首页</title>
    </head>
    <body>
        <div id="ui_automation_t">
            <h1>这个是标题1</h1>
            <p>这个是测试信息</p>
        </div>
    </body>
</html>

If we want to locate the corresponding label element, our XPath relative path can be written like this:

//div[@id='ui_automation_t']/p

How to understand this relative path? It's actually very simple. Let's interpret it based on the relative path keywords above.

First // starts from the root node, div searches for all div elements below, then searches for elements with the id attribute value ui_automation_t in all div elements, and finally locates all p elements below in the matched results. The advantage of relative path positioning is that there is no need to consider the impact of element path changes caused by structural changes, unless the element itself changes or is cancelled.

2. Use of relative path operators

In XPath's relative path positioning, we can also use operators to position corresponding attributes. Many conditional judgments can be achieved using operators.

【equal】

It is easy to understand that the equal operator is used to match whether the attribute value of the element is equal to the specified value.

driver.find_element(By.XPATH, "//input[@name='discount']")

【Include】

The contains() function is used to match whether an element's attribute value contains a specified string.

driver.find_element(By.XPATH, "//input[contains(@class, 'icon-title')]")

【And or】

Both and and or are logical operators that can be used to connect multiple expressions.

driver.find_element(By.XPATH, "//input[@name='discount' and @type='content']")

3. Axis

Now that we are talking about XPath, we cannot get around the concept of "axis". To put it bluntly, it is used to represent a large collection of nodes in the current page. Mastering the usage of axis can help us quickly locate the nodes in the page. In complex Pages often have multi-layer nested structures. We can skip some irrelevant nodes to directly locate the required nodes (avoiding traversal), thus improving the execution efficiency of the script.

Similarly, let's take a look at some basic definitions related to axis:

  • ancestor axis - selects all ancestor nodes of the current node

  • descendant axis - selects all descendant nodes of the current node

  • parent axis - select the parent node of the current node

  • child axis - selects all child nodes of the current node

  • preceding-sibling axis - selects all sibling nodes before the current node

  • following-sibling axis - selects all sibling nodes after the current node

  • self axis - select the current node itself

【ancestor axis】

For example, there is the following HTML code:

<div class="k_interface">
  <div class="c_app">
    <span class="g_center"></span>
  </div>
</div>

If we want to locate the ancestor element (parent) of the span element, we can use the ancestor axis to achieve this:

driver.find_element(By.XPATH, "//span[@class='g_center']/ancestor::div[@class='k_interface']")

The above relative path expression uses the ancestor axis. The ancestor means using this axis to search for the ancestor element on its node after the positioning result of //span[@class='g_center'], and the ancestor element is designated as div[ @class='k_interface'].

But one thing to note here is that the results of axis positioning are a collection of nodes, so we need to call the find_element method when positioning, and never use find_elements. If we want to select all the nodes in the node, we This can be achieved using the ancestor-or-self axis. The usage is the same as above. Just call find_element and replace the ancestor with the ancestor-or-self keyword.

【descendant axis】

The sample code is as follows:

<div class="k_interface">
  <div class="c_app">
    <span>test_page</span>
  </div>
  <div class="c_app">
    <input id="text" placeholder="Enter your case">
  </div>
  <div class="g_center">
    <button>Submit</button>
  </div>
</div>

When you need to locate the descendant elements of the k_interface element, you can use the descendant axis to achieve this:

driver.find_element(By.XPATH, "//div[@class='k_interface']//descendant::input[@id='text']")

If you need to query all descendant elements related to it, use the wildcard * instead:

driver.find_element(By.XPATH, "//div[@class='k_interface']//descendant::*")

The descendant elements in the descendant axis above are also similar to the previous child elements. All indirect and direct descendant elements under its parent node can be obtained.

【parent axis】

The sample code is as follows:

<div class="k_interface">
  <p class="c_app">test_index</p>
</div>

To find the parent element of an element, we can use the parent axis to achieve this:

driver.find_element(By.XPATH, "//p[@class='c_app']/parent::div")

Here we get its parent element div through the class attribute c_app of the p element. Similarly, when you need to obtain plural numbers, just use * to represent it.

【child axis】

There is the following piece of code:

<div class="k_interface">
  <div class="c_app">
    <span class="g_center">test_group_1</span>
  </div>
  <div class="c_app">
    <span class="g_center">test_group_2</span>
  </div>
</div>

If we want to get the test_group_2 element under the second-level div element under the parent element, we can use the child axis.

driver.find_element(By.XPATH, "//div[@class='k_interface']/*[2]/*")

After using the child axis to obtain it, /*[2]/* represents the descendant element test_group_2 under the second div element.

【preceding-sibling 轴】

The sample code is as follows:

<ul>
  <li>Beijing</li>
  <li>Shanghai</li>
  <li class="selected">Guangzhou</li>
  <li>Nanjing</li>
  <li>Jinan</li>
</ul>

If we want to locate the two elements Beijing and Shanghai, we can use the following path expression.

driver.find_element(By.XPATH, "//li[@class='selected']/preceding-sibling::li[position()<=2]")

//li[@class='selected'] in the code will select the Guangzhou element, because the class attribute is specified here, and then we use the preceding-sibling axis to select all sibling elements before the element, plus the use of li [position()<=2] to filter out the first two elements.

【following-sibling 轴】

Still the same set of code:​​​​​​​

<ul>
  <li>Beijing</li>
  <li>Shanghai</li>
  <li class="selected">Guangzhou</li>
  <li>Nanjing</li>
  <li>Jinan</li>
</ul>

If we need to select the two elements Nanjing and Jinan, we can use the following path expression.

driver.find_element(By.XPATH, "//li[@class='selected']/following-sibling::li")

Similarly, //li[@class='selected'] does not need to be explained. Here, the following-sibling axis is used to select all sibling elements after the element. Because all subsequent elements are selected here, there is no need to specify The location conditions are filtered, just specify the tag name directly.

【self axis】

The example code is as follows:​​​​​​​

<div id="a_word">
  <p class="selected">The word is a.</p>
</div>

If we want to select the p element here, we can directly use the self axis.

driver.find_element(By.XPATH, "//p[@class='selected']/self::node()")

The above code uses self::node() to represent the currently selected node, but it is different from other axis properties. Generally, we use it directly. There is no need to spend a lot of time.

4. Function

In the relative path positioning method above, we can see some usage of functions, such as position()<=2, etc. In fact, the XPath positioning method supports a variety of built-in functions. Making good use of these built-in functions can also help us be more accurate and efficient. to locate the elements you need. Below we will introduce some commonly used built-in functions.

starts-with()

This function is used to match whether the element's attribute value begins with the specified string.

driver.find_element(By.XPATH, "//input[starts-with(@id, 'ke')]")

As shown in the above code, here we use starts-with to match whether the id attribute of the element starts with ke.

contains()

This function is used to check whether the text content in the element contains the specified string.

driver.find_element(By.XPATH, "//div[contains(text(), 'fill')]")

Here we use contains to check whether the text content of the div element contains fill.

substring()

This function is used to intercept the specified part of the string.

driver.find_element(By.XPATH, "//span[substring(text(), 1, 3) = 'key']")

The above code intercepts the span element, and the intercepted content is the first three characters. The = 'key' here is used to compare the results to see whether the intercepted result is equal to the specified character content. It should be noted that the starting number of matching is 1, rather than starting from 0 in the subscript. If the comparison result does not match, the search result of this element will still throw a NoSuchElementException exception.

count()

The count function is used to get the number of specified elements. ​​​​​​​

if driver.find_elements(By.XPATH, "count(//div[@class='advance']) > 1"):
    print("找到了符合条件的元素!")
else:
    print("没有找到符合条件的元素。")

Here we directly use the count function to determine the number of elements and return the corresponding print results.

elements = driver.find_elements(By.XPATH, "count(//div[@class='my-class']) > 1")
if elements:
    print("元素个数大于 1")
else:
    print("元素个数小于等于 1")

The judgment method is arbitrary, but when using the count function, you need to use the find_elements method instead of find_element.

Points to note

The above are some advanced element positioning techniques of CSS Selector and XPath. So what are the points that need to be paid attention to in our daily work?

Notes on using CSS Selector

When using CSS Selector to locate elements, try to avoid using a certain attribute alone to position, such as div tags. There must be multiple elements on the page. Using them alone will cause multiple elements to be positioned and cannot be specified, resulting in an error.

If you are not completely sure, try to use * wildcards as little as possible for positioning. It will often match all the elements of a certain node or all the elements of a specified feature. This result is particularly terrible in the later script running or maintenance stages.

You must be familiar with the syntax of combined positioning and selectors. You must be familiar with when to use spaces and when to use specific symbols. Most of the characters in the code are in English. Once you use these incorrectly, these characters and spaces will become confused during troubleshooting. More difficult.

There will also be some dynamically generated element attributes in the page. Many students doing test development have encountered this. We generally use attributes to assist in positioning.

Some students like to use selectors in a nested form, which is not impossible, but such a programming form will invisibly reduce the readability of the code itself and increase the cost of later maintenance, which is not worth the gain.

Notes on using XPath

Don't use absolute paths, don't use absolute paths, don't use absolute paths, say important things three times.

Compared with pages with more elements or more complex structures, use relative paths and combine axes, operators, and built-in functions to improve the simplicity and accuracy of expressions and improve the readability of the code.

For a relatively complicated expression, you can try to disassemble it and express it. This is also one of the techniques to improve the efficiency of test execution.

You can check the copy xpath in the developer tools in the browser, but it is just for reference, and it is not very practical.

Finally: The complete software testing video tutorial below has been compiled and uploaded. Friends who need it can get it by themselves [guaranteed 100% free]

Software Testing Interview Document

We must study to find a high-paying job. The following interview questions are from the latest interview materials from first-tier Internet companies such as Alibaba, Tencent, Byte, etc., and some Byte bosses have given authoritative answers. After finishing this set I believe everyone can find a satisfactory job based on the interview information.

​​​​

Guess you like

Origin blog.csdn.net/weixin_50829653/article/details/132909360