? 6.1 Common positioning methods explained
Object positioning is a critical step in automated testing, and it can be said to be the most critical step, after all, you don't have a target, so you can't do it. So the knowledge of this chapter I hope that we do more hands-on operation, not just the knowledge of books, after all, this I can only illustrate. Let's look at some of the ways we used to locate them.
6.1.1 ID Location
Whether in Web Automation or app automation, the ID is unique, there may be some small partners see here will be questioned, because some of the information is the name of the location is unique, why you are here is the ID, in fact, this is not in conflict before, but if you use a newer version of Appium is not possible , in the new version of the name is removed, so there will be no name in the future positioning, usually we prefer to use the ID to locate. There may be questions about the little buddy you just learned here, sometimes your app doesn't have an ID, or it's on the phone but not on the other. 1, the development did not add. 2, Android version is below 4.4.
Let's look at this picture directly below
The ID of the object on the left side of the image above is circled in red. We can see in the property of the right, his ID is also circled in red, if we need to "mobile phone number/mailbox" This input box to enter information, we just have to manipulate the ID on the right side of the line, the following we look directly at the code.
driver.find_element_by_id ("Cn.com.open.mooc:id/account_edit"). Send_keys ("111111")
Through the above code we can directly in the User information input box to enter user information 111111. It might be a bit confusing for people without foundation, where the driver came from, driver was initialized when we configured the boot, we just need to call his method find_element_by_id. If your IDE has auto-complete functionality, you'll find a problem when you enter the following method, why do you have a find_elements_by_id? We'll explain this in the back, and we can think about it.
6.1.2 ClassName Positioning
In the actual work, classname positioning is relatively less. When you often go to see the class you will find a lot of classname is the same, you have no way to the unique positioning, below we look at the following two photos
We can take a closer look at the two pictures in the phone number, password two input box classname are the same, if in this case you use
Driver.find_element_by_class_name ("Android.widget.EditText"). Send_keys ("111111")
This way to locate, you will find that you can never locate the password bar, which is why? Because in the design time if you find the element in the page has multiple, the system will automatically give you the first choice, so you can never operate the back, then how to solve this problem? Let's look at the explanation later.
6.1.3 XPath positioning
XPath targeting is the most common and most effective in Web automation, and using XPath positioning avoids the problem of missing elements causing an error, but using XPath targeting in the app is a low thing. Why do you say that? Because in the author's experience, as long as you meet with the XPath positioning element his reaction will be slow, the purpose of automation is to improve efficiency, but the use of XPath will reduce efficiency, so it says very low. But most of the time we have to understand, below we probably explain. First, we should familiarize ourselves with the XPath positioning of the web.
Before you speak the Web XPath, install the Firebug and Firepath two plugins in the browser before everyone installs the Firefox browser. Such as:
These two plug-ins are essential when automating or learning XPath, and here we go directly to XPath, so let's take a look at the following picture to understand
Circled in red with dashed input boxes Let's look at the positioning Xfirepath gives us, which is shown in the XPath in the positioning ".//*[@id = ' kw ']", what does this mean? Let's take one step at a to explain. 1.//* selects all elements in the document. 2, @id = ' kw ') matches a node with an ID and a value of KW. Some of the small partners here may not quite understand that it is OK to use the ID directly to locate it. In fact, but when there is no such attribute? Let's look at this picture below
If the name is not valid, how do you position it if you do not use XPath when you see the image? There's some crazy feeling. Small partners can try to use XPath to locate, some people may find that the XPath is not very clear positioning, why?.//*[@id = ' U1 ']/a[4] In this XPath, we don't have the same clarity as we did before. He had some more hierarchical relationships, We'll talk about this later. In this XPath first step 1, @id = ' U1 ' is the same as the previous match attribute to the node with the ID value of UL, and then under his position 2,/a[4] means to select the fourth a element from the root node. Is this step-by-step analysis easier to understand? Let's take a look at some of the syntax that is often used in XPath positioning, and come down and practice a lot.
This is what we often use, and is the most basic knowledge, only these do not have the means to complete a lot of weird needs, then there are more difficult, below we look at the following list
The above knowledge is in the http://www.w3school.com.cn/xpath/xpath_examples.asp inside, everyone down after must see more, more practice.
Below we look directly at the use of XPath in the app
In the above two pictures we can clear the see their ID, classname are the same, such a situation without hierarchical positioning method we can only use XPath to locate, first of all, according to the previous web learning you can think about how to locate. We look directly at the code
Driver.find_element_by_xpath ("//android.widget.textview[@text = ' JavaScript ']"). Click ()
In XPath, our syntax is "//android.widget.textview[@text = ' JavaScript '", which, like our previous web XPath, It means to find the node in all nodes as Android.widget.TextView (using classname, or ID, and the system will look in turn) and his text property value is JavaScript, is it easier to understand? Come down and practise more. Such a positioning method is not recommended, the efficiency is very slow.
6.2 Level positioning 6.2.1 What is hierarchical positioning
In the previous chapters we have mentioned the level of positioning, just do not know how to do it. In a lot of automation if just rely on simple positioning is no way to complete the automation, like just XPath positioning, some elements of the ID, name, classname are the same, XPath positioning inefficient, this time most of us will use hierarchical positioning.
How to apply the hierarchical positioning in the 6.2.2 project
Let's take a simple example to understand hierarchical positioning.
From the picture above we can see that the node with ID Cn.com.open.mooc:id/rv_child contains a lot of android.widget.FrameLayout
From this picture we can see that if we want to locate this element we are not able to locate, this situation most of us use hierarchical positioning and XPath, here we see how to use hierarchical positioning.
First we can see the structure of the two pictures of the difference, the second picture element he is in the first picture, here we call the first image of the Cn.com.open.mooc:id/rv_child node is the second graph element of the parent node, we only need to first through the ID to the parent node, Then you can locate it from the parent node down the side. Now can you practice it and see what I have done? Look at the code:
element = driver.find_element_by_id ("Cn.com.open.mooc:id/rv_child") Element.find_element_by_class_name (" Android.widget.FrameLayout "). Click
According to thinking our code will be the result above, but you go to run will find no error, can also not click, this is why? Let's look at the picture below
All child nodes under the parent node his classname are "Android.widget.FrameLayout", and in this case how did he click on the operation? So in this case there will be a new positioning problem, which is what we are going to talk about list positioning.
6.3 List Positioning
List so the name is a listing, in Python there is also a list of this argument, if you do not understand what is a list, here for the moment to understand as an array or a set. First a list is a collection, then his number is also a uncertainty, so it needs to use complex numbers, so in our positioning we can not continue to use find_element_by_id and so on positioning method, we need to use his plural form find_elements_by_ ID, all positioning methods need to use the plural plus s. Here we go on to the above case, how to use list to locate the element you want to locate. First look at one piece:
We look at the picture to know that we can easily navigate through the ID to the entire parent node, we need to do the next thing to locate all the "android.widget.RelativeLayout" node under the parent node, the same first we look at a picture:
Here we need to directly use the method of locating complex numbers to see the code directly:
element = driver.find_element_by_id ("Cn.com.open.mooc:id/rv_child") elements = Element.find_elements_by_class_ Name ("Android.widget.RelativeLayout")
Through the above code we directly locate all the android.widget.RelativeLayout child nodes under the Cn.com.open.mooc:id/rv_child parent node, and now we need to manipulate this child node, here are two ways:
1, before we talked about list you can be understood as an array or a set, where all the child nodes positioned at the end of a list, if we want to access the list of one of the elements we can access the same as the data in the array by subscript access. The final code is like this:
element = driver.find_element_by_id ("cn.com.open.mooc:id/rv_child") elements = Element.find_elements_by_class_name ( "Android.widget.RelativeLayout") Elements[1].click ();
The final result of the above code is to select the JavaScript tab and click Enter.
Note: If beginners do not understand how to access through the subscript, here is the subscript is starting from 0, if you want to access the first element of the list I The result is i[0], this part of the knowledge will be discussed later in the Python Foundation.
2. If you want to access the elements inside the list, can we access them sequentially through the FOR Loop statement? This is often used in automation. Below you can through this idea oneself go to actual combat, see whether can achieve the expected effect. See My code below:
element = driver.find_element_by_id ("cn.com.open.mooc:id/rv_child") elements = Element.find_elements_by_class_name ( "Android.widget.RelativeLayout") for Ele in elements: Ele.click ()
Looking at the code above, we loop through each element of the list, because each loop gets one of the elements, then we just need to add the action you want on this element, so we can click it directly.
If you do, you will find a problem here, you go to the first label after a while the system will be error, why? You can also try to solve this problem, we will explain this piece of knowledge later.
6.4 Embedded H5 positioning 6.4.1 Hybrid positioning thinking
In Web Automation we will meet the problem of frame, after meeting these embedded tags we need to do is to switch windows, then in the app Automation test also has a similar situation is we often see the embedded HTML, in our native app to add a page made of HTML. Let's think about how this can be done.
Analysis of common locating problems of 6.4.2 hybrid
First, let's take a look at the following picture:
Through the right structure we can clearly see the entire page is a webview, no matter from what point of view we are not able to do very well, if this time we need to manipulate the elements of the page needs to be done by switching contexts. But before we talk about this knowledge, we should first try to deal with this page according to the knowledge on the Internet, and see if we can succeed. Here are some of the questions that you will meet first:
1, you may see some articles show that we do not need to switch contexts to be able to complete the positioning, such a situation, but that the situation of the author only in the Micro-blog login, QQ login and other third-party login encountered, if not the case and like the above situation can not be done by a similar method, So I hope that when the reader encounters this situation, he will do the work and see what is more appropriate for his project.
2, need to switch contexts then need to get all the contexts page, at this time you through the website or other knowledge of the article through the following methods to obtain, may be error, this situation is not very related.
WebView = Self.driver.contextsprint WebView
If you use the above code to debug but the error, but other information is not a problem when you do not worry, here you need to determine two things: (1), the app needs to open the WebView debug Properties setwebcontentdebuggingenabled ( True), this directly lets the development add just as well. The general situation is open, after all, they also have to debug. (2), you use a lot of mobile phone to debug, found some can have some may not, but you use the simulator can, according to the official answer is this time you need to go to the phone root, and then try again. At present, the author met the two cases, the second I also debugging for a long time to find the reason.
6.4.3 Hybrid Positioning explanation
These two problems after the solution so positioning WebView easy to take care of, directly look at the code:
WebView = Driver.contextsdriver.switch_to.context (webview[1]) driver.find_element_by_link_text (' PHP '). Click ()
For beginners may not be very understanding of the above code, let's look at the log:
You don't have to worry about me. Execute the code and the previous difference (more than a self), we look at the output of the console below, the output is a list, the previous said list and array similar, in this list there are two elements "Native_app", "webview_cn_com_ Open_mooc ", the first element is the contexts of our native app, followed by the context of our webview, so we need to get the webview context only through the list of the following table to access.
We only need to switch through Driver.switch_to.context () when we get to the webview context. When we switch, we can navigate like a web.
Take a look at the picture below we open the H5 page via our browser:
With the images above we can easily navigate like a web, and we can use some of the web's positioning methods. Do you see that this solves a problem? Go ahead.
6.4.4 Hybrid Problem Combat
Through the previous study I believe you have a number of practical abilities, here to ask you a question, we get to the contexts each must be two? If it weren't for two, wouldn't the script above be useless? Can think about how to solve here, looking at our following ideas and solutions.
No matter what page we go to get contexts when he has a few but his type is certainly a list? Since it is a list then can we take every value in it and then judge each value, just to find out our webview? Here's a look at the code:
#获取当前页面所有的contextswebview = driver.contexts# in the retrieved contexts list to cycle for the context in WebView: # Determines whether a single context in the loop is WEBVIEW, toggles if it is, and jumps out of the loop if ' WEBVIEW ' in context: Driver.switch_to.context (context) Breakdriver.find_element_by_link_text (' PHP '). Click ()
Does the above code solve the problem of positioning the embedded H5 perfectly? Do it
6.5 Sliding positioning 6.5.1 Slide positioning method
In app automation we often encounter a problem, we need to find the element is not in the currently available screen, as to where we do not know, if this time we have been using the current page to find, then the system will be error, in order to solve this problem we need to use the swipe to find.
The first idea is that we look up the element on the page that needs to find the object, determine whether the element is on the current page, and if that element is not on the page then we need to go to the interactive screen, to our next screen, then to find, and so on.
Analysis on the thinking of 6.5.2 sliding positioning
The way we have it, then we need to know what points to implement this function. Follow me here to analyze:
1, need to find the elements we need to know what is it? This needs to be determined first.
2, we need to find the page is on the top or bottom of our current page or the left or the right, we can not be sure, then we need to determine the direction we need to slide?
3, element and direction have, but do you know how much we need to slide the screen every time? So do we need to get the size of the screen first and then calculate a sliding value for different directions?
Everything has only the East wind, to follow this idea of hands-on practice.
6.5.3 Sliding positioning combat
First, according to the above ideas we can start to determine what we need to find the element, see the following image:
We need to find the actual combat recommended "swap" button, then click. First we look at his location information.
Finally we find the location information code for the element as follows:
self.driver.find_element_by_id (' Cn.com.open.mooc:id/tv_replace '). Click ()
For a certain base of people may feel this is very low, but have not thought of a problem, we can through this code to execute, in the absence of this button will be error, there is no way to carry on, then how to deal with it? So this time we need to have some Python fault-tolerant knowledge, even if our code execution is wrong, then we have to let him follow our meaning execution. Try.......except., this is the fault-tolerant processing in our Python, let's look at the added code:
try:self.driver.find_element_by_id (' Cn.com.open.mooc:id/tv_replace '). Click () except Exception,e:print E
Try means to tell the compiler to try to execute his code below, and if it does, then you can print out the error message inside the except.
Second, with the elements now we need to know is not how to slide the interface? First, let's take a look at the following picture:
In the process of using the app there are several sliding situations, we look at the entire interface as a coordinate system (x, y), if we need to swipe up, then we are not moving the x-axis, the y-axis from the bottom of the upward motion? Down is the x-axis, the y-axis from the top down? So is the left or right slide the x-axis of the y-axis? Can be a good experience, there is a picture in my mind.
The way we need to slide in the appium is the swipe function, and as for which direction to slide is to see the value of X, y in us, and if we need to swipe up, then we should be:
Self.driver.swipe (x1,y1,x1,y2,t)
The value of the x-axis of the above code does not change, the value of the y-axis is changed, so it is sliding along the top and bottom, sliding from y2 to the Y1 point. T stands for how much time it takes to complete this action, or how long it lasts.
Note: It should be noted here that the value of x, y of the screen is taken from the upper left corner, the upper-left corner is (0,0), and the lower-right corner is the largest.
Third, the above sliding method looks good, but we can not always fill in a coordinate, so too low, so we need to get the screen size, directly look at the code:
x = Self.driver.get_window_size () [' width ']y = self.driver.get_window_size () [' Height ']
The code above is the x, Y axis we get. Through the idea of our code has, the next thing we want to do is to modify the original code, to carry out a package. Look at the code below, this temporarily do not understand the matter, to the back we learned the Python ' foundation can be understood. First thought, then understand.
#获取屏幕大小 def getsize (self): x = self.driver.get_window_size () [' width '] y = self.driver.get_window_size () [' Height '] return (x, y) #向左滑动def swipeleft (self,t): L=self.getsize () x1=int (l[0]*0.9) y1=int (l[1]*0.5) x2=int (l[ 0]*0.1) Self.driver.swipe (x1,y1,x2,y1,t) #向右滑动def swiperight (self,t): L=self.getsize () x1=int (l[0]*0.25) Y1=int (l[1]*0.5) x2=int (l[0]*0.75) self.driver.swipe (x1,y1,x2,y1,t) #向上滑动def swipeup (self,t): L=self.getsi Ze () x1=int (l[0]*0.5) y1=int (l[1]*0.8) y2=int (l[1]*0.4) self.driver.swipe (x1,y1,x1,y2,t) time.sleep (5) #向下滑动de F Swipedown (Self,t): L=self.getsize () x1=int (l[0]*0.5) y1=int (l[1]*0.25) y2=int (l[1]*0.75) self.driver.swipe (x1,y1,x 1,Y2,T) #查找元素, did not find the sliding def findlocal (self): x = 1 while x==1:if self.fact () = = 1:self.swipeup (+) Ti Me.sleep (3) self.fact () else:print "found" x=2 #递归def fact: N =1 try: Self.driver.find_element_by_id (' Cn.com.open.mooc:id/tv_replace '). Click () except Exception,e:return n
By looking at the entire logic of the above code is 1, first to find the element, if found I will directly click. 2, if the element is not found then I will swipe up (here you can choose), swipe after the search again, if found on the click, did not find to continue to swipe. Hands-on, here the knowledge point is very important! Although there are some workarounds later, the idea and algorithm are important.
Positioning of elements of the Appium Python Automation Test series (VI)