Monkenrunner methods and recommendations for positioning controls via Hierarchyviewer (Appium/uiautomator/robotium sister article)

Source: Internet
Author: User
Tags appium

1. Background

In the use of monkeyrunner, we often use the chimchat below the Hierarchyviewer module to get some information about the target control to assist us in testing, but on the Monkeyrunner's official website did not see the corresponding API description, Only the following three classes of API reference information (http://developer.android.com/tools/help/MonkeyDevice.html)

    • Monkeydevice
    • Monkeyimage
    • Monkeyrunner
So here's an attempt to sort out the usage of the API provided by Hierarchyviewer and make recommendations based on the practice, first look at all the available public methods that the class provides, not much: you can see that the methods provided in the Hierarchyviewer class are primarily used to locate control-related , including the control based on the ID, the position of the control on the screen, and so on. But there are other ways we'll describe it in passing, after all, not much. In this article we still follow a few articles as the SDK comes with the Notepad as the experimental target, see how to locate the noteslist below the menu options in the Add note this menu Entry. The following is the target device interface obtained by Hierarchyviewer: 2.findViewById (String ID) 2.1 Example
TargetDevice = Monkeyrunner.waitforconnection () "Public     Viewnode Findviewbyid (String ID)      * @param ID-ID for The view.     * @return view with the specified ID, or {@code null} if no view found. " Viewer = targetdevice.gethierarchyviewer () button = Viewer.findviewbyid (' id/title ') Text = viewer.gettext (button) print Text.encode (' Utf-8 ')
2.2 Analysis and recommendation the purpose of this API is to obtain a Viewnode object representing the user control through the control's ID. Because this is the first example, here are a few things to explain
    • Once the Monkeyrunner is connected to the device, a Monkeydevice object is immediately represented on the target test device, and we are using this device object to control the device's
    • Note that the ID you need to fill in the format and Uiautomatorviewer get ResourceID is not the same, please see Uiautomatorviewer in front of ResourceID more "Android:" String:
    • This method returns a Viewnode object that represents the target control, has a large number of control-related properties, and since the length issue is not detailed here, a separate article should be written to describe its use. In this article, I know it represents the target control.
    • The reason for the final printing to be converted to UTF-8 encoding is related to the default encoding format of Jython, which is described and workaround please see: http://www.haogongju.net/art/1636997
3. Findviewbyid (String ID, Viewnode rootNode) 3.1 Example
"Public     Viewnode Findviewbyid (String ID, viewnode rootNode)      * Find A view by ID, starting from the given root n Ode     * @param ID ID of the view you ' re looking for     * @param rootNode the viewnode at which to begin the Traversal
   * @return View with the specified ID, or {@code null} if no view found.     " Iconmenuview = Viewer.findviewbyid (' id/icon_menu ') button = Viewer.findviewbyid (' Id/title ', Iconmenuview) print " Button Text: ", Text.encode (' Utf-8 ')
3.2 Analysis This method is an overload of the method above, in addition to specifying the ID, you also need to specify a rootnode, the RootNode refers to the known control of the parent control, the parent to what level there is no limit. Why this method is needed, we can imagine this: there are two controls on the same interface that have the same ID, but one of their hierarchical parent controls begins to fork. Then we can specify the RootNode as the parent control (not included) to one of the parent controls in the path to the target control (not included) to precisely locate the target control we need. As our example shows, it is clear that what we need is the "id/title" control under the parent control "Id/icon_menu" (see Hierarchyviewer in the background). 4 Getabsolutepositionofview (Viewnode node) 4.1 Example
"Public    Static point Getabsolutecenterofview (Viewnode node)     * Gets the absolute x/y center of the specified vie W node.     *     * @param node view node to find position of.     * @return Absolute x/y center of the specified view node.     */"point = Viewer.getabsolutecenterofview (button) print" button Absolute Center Position: ", point
4.2 Analysis and recommendations The purpose of this API is to locate the absolute coordinates of the upper-left corner of a known Viewnode control on the screen. For our normal app inside of the controls, I have practiced there is no problem.But there is one case to pay special attention to: this is not valid for the control below the menu options! The output of the last piece of code in the above example is (3,18), in fact, it is not necessary to know that this can not be relative to the upper left corner of the coordinates (0,0) of the absolute coordinate values, offset this a little bit of pixels, you really when my experimental machine HTC Incredible S is the artifact that can implant the brain ah. So how is this data obtained? In fact, according to my understanding (It's really just my own understanding, wrong words, but please describe the details for my reference), the definition of this function should be "get from the top of the Decorview (specific Dectorview description Please see my previous CSDN reprint of an article"An analysis of Android Decorview") The upper-left coordinates to the offset coordinates of the target control", but the coordinates of the top-most decorview are generally starting from (0,0). If I think that the top framelayout represents the Decorview, or the entire form then, assuming my point of view is right, this is good parsing, see the absolute coordinates of the top framelayout of menu option are (0, 683) and the absolute coordinate of the add note is (3,701) the subtraction of the two is absolutely consistent with our output (3,18). 5. Getabsolutecenterofview (Viewnode node) 5.1 Example
"Public    Static point Getabsolutecenterofview (Viewnode node)     * Gets the absolute x/y center of the specified vie W node.     *     * @param node view node to find position of.     * @return Absolute x/y center of the specified view node.     */"point = Viewer.getabsolutecenterofview (button) print" button Absolute Center Position: ", point
5.2 Analysis and recommendations The purpose of this method is to obtain the absolute coordinate value of the middle point of the target Viewnode control, butThe controls below the menu options also do not apply, see the 3rd section for details。 The following two methods are not used to locate controls and are recorded for reference. 6. Getfocusedwindowname () 6.1 Example
"Public    String getfocusedwindowname ()     * Gets The window that currently receives the focus.     *     * @return name of the window that currently receives the focus. window = Viewer.getfocusedwindowname () print "Window Name:", Window.encode (' Utf-8 ')
6.2 Parsing is actually getting the packagename/activityname of the currently open window, and the output is consistent with the information detected by the Hierarchyviewer tool, so guess it uses the same method. Output: Hierarchyviewer monitoring information: 7. Visible (Viewnode node) 7.1 Example
"Public    Boolean visible (Viewnode node)      * Gets The visibility of a given element.     * @param selector selector for the view.     * @return True If the element is visible. " isVisible = viewer.visible (button) print "is visible:", isVisible
is to see if the control is visible, nothing to parse. 8. Test code
From Com.android.monkeyrunner import monkeyrunner,monkeydevicefrom com.android.monkeyrunner.easy Import Easymonkeydevice,byfrom com.android.chimpchat.hierarchyviewer Import Hierarchyviewerfrom Com.android.hierarchyviewerlib.models Import Viewnode, Windowfrom java.awt import Point#from Com.android.hierarchyviewerlib.device import #Connect to the target Targetdevicetargetdevice = Monkeyrunner.waitforconnection () Easy_device = Easymonkeydevice (targetdevice) #touch a button by ID would need thistarget Device.startactivity (component= "Com.example.android.notepad/com.example.android.notepad.noteslist") #time. Sleep     (a) #invoke the menu Optionsmonkeyrunner.sleep (6) targetdevice.press (' Keycode_menu ', monkeydevice.down_and_up);     Public Viewnode Findviewbyid (String ID) * @param ID ID for the view. * @return view with the specified ID, or {@code null} if no view found. " Viewer = targetdevice.gethierarchyviewer () button = Viewer.findviewbyid (' id/title ') Text = viewer.gettext (button) print Text.encode (' utf-8 ') ' Public Viewnode Findviewbyid (String ID, viewnode rootNode) * Find A view by ID, starting  From the given root node * @param ID ID of the view you ' re looking for * @param rootNode the Viewnode in which to     Begin the traversal * @return view with the specified ID, or {@code null} if no view found. "' Iconmenuview = Viewer.findviewbyid (' id/icon_menu ') button = Viewer.findviewbyid (' Id/title ', Iconmenuview) ' print ' Button Text: ", Text.encode (' utf-8 ') ' Public String getfocusedwindowname () * Gets the window that currently receive     s the focus. * * @return Name of the window that currently receives the focus. window = Viewer.getfocusedwindowname () print "Window Name:", Window.encode (' utf-8 ') ' public static point Getabsolutece     Nterofview (Viewnode node) * Gets the absolute x/y center of the specified view node.     * * @param node view node to find position of.     * @return Absolute x/y center of the specified view node.*/"point = Viewer.getabsolutecenterofview (button) print" button Absolute Center Position: ",", "the" public static Poin     T Getabsolutepositionofview (viewnode node) * Gets the absolute x/Y position of the view node.     * * @param node view node to find position of. * @return Point specifying the X/Y position of the node. Point = Viewer.getabsolutepositionofview (button) print "button Absolute Position:", the point ' public boolean visible (View     Node node) * Gets The visibility of a given element.     * @param selector selector for the view. * @return True If the element is visible. " isVisible = viewer.visible (button) print "is visible:", isVisible
9. Attach the source code of the Hierarchyviewer class for easy reference
/* Copyright (C) The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License") ; * You are not a use this file except in compliance with the License. * Obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * unless required by appli Cable law or agreed into writing, software * Distributed under the License is distributed on a "as is" BASIS, * without Warranties or CONDITIONS of any KIND, either express OR implied. * See the License for the specific language governing permissions and * limitations under the License. */package Com.android.chimpchat.hierarchyviewer;import Com.android.ddmlib.idevice;import Com.android.ddmlib.Log; Import Com.android.hierarchyviewerlib.device.devicebridge;import Com.android.hierarchyviewerlib.device.viewserverdevice;import Com.android.hierarchyviewerlib.models.ViewNode; Import Com.android.hierarchyviewerlib.models.window;import org.eclipse.swt.graphics.point;/** * Class for querying the view hierarchy of the device.    */public class Hierarchyviewer {public static final String TAG = "Hierarchyviewer";    Private IDevice Mdevice;     /** * Constructs the hierarchy viewer for the specified device.     * * @param device The Android device to connect to.        */Public Hierarchyviewer (IDevice device) {this.mdevice = device;    Setupviewserver ();        } private void Setupviewserver () {Devicebridge.setupdeviceforward (mdevice); if (! Devicebridge.isviewserverrunning (Mdevice)) {if (!                Devicebridge.startviewserver (Mdevice)) {//Todo:get rid of this delay.                try {thread.sleep (2000); } catch (Interruptedexception e) {} if (!                    Devicebridge.startviewserver (Mdevice)) {LOG.E (TAG, "Unable to debug device" + Mdevice);               throw new RuntimeException ("Could not connect to the View server"); } return;    }} devicebridge.loadviewserverinfo (Mdevice);     }/** * Find a view by ID.     * * @param ID ID for the view.     * @return view with the specified ID, or {@code null} if no view found.  */Public Viewnode Findviewbyid (String id) {Viewnode rootNode = devicebridge.loadwindowdata (new        Window (new Viewserverdevice (Mdevice), "", 0xFFFFFFFF));        if (RootNode = = null) {throw new RuntimeException ("Could not Dump View");    } return Findviewbyid (ID, rootNode);     }/** * Find a view by ID, starting from the given root node * @param ID ID of the view you ' re looking for * @param rootNode the viewnode at which to begin the traversal * @return view with the specified ID, or {@code null} I     F no view found. */Public Viewnode Findviewbyid (String ID, Viewnode rootNode) {if (RootNode.id.equals (ID)) {return        RootNode; } for (VieWnode child:rootNode.children) {Viewnode found = Findviewbyid (Id,child);            if (found! = null) {return found;    }} return null;     }/** * Gets The window that currently receives the focus.     * * @return Name of the window that currently receives the focus.        */Public String getfocusedwindowname () {int id = Devicebridge.getfocusedwindow (mdevice);        window[] Windows = devicebridge.loadwindows (new Viewserverdevice (Mdevice), mdevice);        for (Window w:windows) {if (w.gethashcode () = = ID) return w.gettitle ();    } return null;     }/** * Gets the absolute x/Y position of the view node.     * * @param node view node to find position of.     * @return Point specifying the X/Y position of the node.        */public static point Getabsolutepositionofview (Viewnode node) {int x = Node.left;        int y = node.top; Viewnode p = node.parent;            while (P! = null) {x + = P.LEFT-P.SCROLLX;            Y + = p.top-p.scrolly;        p = p.parent;    } return new Point (x, y);     }/** * Gets the absolute x/y center of the specified view node.     * * @param node view node to find position of.     * @return Absolute x/y center of the specified view node.        */public static point Getabsolutecenterofview (Viewnode node) {Point point = Getabsolutepositionofview (node);    return new Point (Point.x + (NODE.WIDTH/2), Point.y + (NODE.HEIGHT/2));     }/** * Gets the visibility of a given element.     * * @param selector selector for the view.     * @return True If the element is visible. */public Boolean visible (Viewnode node) {boolean RET = (node! = null) && Node.namedprop Erties.containskey ("getvisibility ()") && "VISIBLE". Equalsignorecase (Node.na MedpropertieS.get ("getvisibility ()"). Value);    return ret;     }/** * Gets the text of a given element.     * * @param selector selector for the view.     * @return The text of the given element. */Public String GetText (Viewnode node) {if (node = = null) {throw new RuntimeException ("Node not fo        und ");        } viewnode.property Textproperty = Node.namedProperties.get ("Text:mtext"); if (Textproperty = = null) {//Give it another chance, ICS viewserver returns mText Textproperty = n            Ode.namedProperties.get ("MText");            if (Textproperty = = null) {throw new RuntimeException ("No Text property on Node");    }} return textproperty.value; }}
10. Refer to the following is the practice of the previous control positioning of different frames, a side by side to facilitate direct jump reference:
    • Robotium Android control positioning practices and recommendations (Appium/uiautomator sister article)
    • Uiautomator ways to locate Android controls practice and advice (Appium sister article)
    • Appium practice and suggestion on the control location method of various findelement based on Android
Author Independent Blog Service number and Scan code CSDN
Heaven Zhuhai Branch Rudder Http://techgogogo.com Service Number : Techgogogo Scan Code : Http://blog.csdn.net/zhubaitian

Monkenrunner methods and recommendations for positioning controls via Hierarchyviewer (Appium/uiautomator/robotium sister article)

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.