Monkeyrunner : Gestion des identifiants de contrôles manquants ou dupliqués

Lors de l'automatisation Android avec monkeyrunner, les opérations s'appuient souvent sur des coordonnées d'écran ou des identifients de contrôles. L'utilisation des coordonnées pose des problèmes de réutilisabilité lorsque la résolution change, car le code doit être ajusté. Par conséquent, l'approche préférée repose sur les identifiants de contrôles, bien que ceux-ci soient principalement applicables sur des émulateurs et non sur la plupart des appareils physiques.

Un défi survient lorsque certains contrôles ont des identifiants inexistants ou dupliqués. Pour surmonter cela, on peut exploiter la structure hiérarchique des vues à l'aide d'outils tels que HierarchyViewer ou uiautomatorviewer. Dans l'arborescence affichée par ces outils, chaque contrôle possède un index numérique indiquant sa position parmi ses frères et sœurs. En identifiant un nœud parent unique, on peut naviguer vers les enfants en utilisant une séquence d'indices.

Par exemple, pour cibler un contrôle avec un identifiant dupliqué, on commence par un parent ayant un identifiant valide, puis on spécifie les indices successifs pour atteindre la vue souhaitée. Cela se traduit par un appel de fonction où le premier argument est l'identifiant du parent racine, suivis des indices des nœuds intermédiaires.

Voici une fonction Python adaptée pour récupérer la référence d'une vue imbriquée. Notez que les noms de variables et la logique ont été modifiés pour améliorer la lisibilité, tout en conservant la fonctionnalité :


def getNestedViewById(rootId, *indexSequence):
    hierarchy = device.getHierarchyViewer()
    refString = "hierarchy.findViewById('" + rootId + "')"
    for idx in indexSequence:
        refString += '.children[' + str(idx) + ']'
    print(refString)
    return eval(refString)

def extractTextFromView(viewObj):
    if viewObj is not None:
        return viewObj.namedProperties.get('text:mText').value

Pour illustrer l'utilisation, considérons une structure où le contrôle cible a un identifiant dupliqué sous un parenet avec l'identifiant 'id/province_list'. En supposant que les indices dans l'arborescence soient 5, 0 et 0 pour les nœuds intermédiaires, on appelle :


targetView = getNestedViewById('id/province_list', 5, 0, 0)

Les indices sont déterminés à partir des outils de visualisation : HierarchyViewer affiche des indices dans les coins des boîtes de contrôle, tandis que uiautomatorviewer les montre devant chaque élément. L'outil uiautomatorviewer, disponible dans le répertoire sdk\tools, offre une alternative conviviale pour examiner l'interface.

Une fois la vue cible obtenue, on peut récupérer ses coordonnées pour effectuer des interactions tactiles. Voici une fonctoin pour obtenir le centre absolu d'un contrôle :


def getCenterCoordinates(viewObj):
    centerPoint = device.getHierarchyViewer().getAbsoluteCenterOfView(viewObj)
    return centerPoint

En combinant ces fonctions, on peut simuler un clic sur le contrôle :


desiredView = getNestedViewById('id/tabs', 1)
point = getCenterCoordinates(desiredView)
device.touch(point.x, point.y, 'DOWN_AND_UP')

Cette approche permet de gérer les cas où les identifiants de contrôles sont manquants ou non uniques, en s'appuyant sur la navigation dans l'arborescence des vues et l'utilisation d'outils de diagnostic.

Étiquettes: MonkeyRunner HierarchyViewer uiautomatorviewer Python

Publié le 14 juillet à 06h00