Opérations avancées de l'interface

Ce chapitre présente des API d'automatisation plus avancées. Vous pouvez utiliser ces interfaces pour effectuer diverses opérations détaillées. Le contenu de ce chapitre est assez dense, donc si c'est votre première fois, nous vous recommandons de lire attentivement chaque section.

Conseil

Lors de l'écriture de code d'automatisation, vous pouvez directement entrer la commande `lamda` dans le terminal à droite du bureau à distance pour exécuter les codes de test suivants ou pour effectuer vous-même des tests de sélection ou de clic d'éléments. Cela peut accélérer votre processus de développement et de validation.

Obtenir un élément

Vous en avez peut-être déjà eu un aperçu dans les connaissances de base ou les chapitres précédents. Vous devez utiliser un sélecteur pour trouver les éléments pertinents avant de pouvoir interagir avec eux. Vous avez probablement aussi vu où obtenir les paramètres du sélecteur. Les explications suivantes se concentreront sur cet élément. Sur le côté droit de l'image, vous pouvez voir les informations relatives à l'élément "同意" (Accepter).

Élément d'exemple

Attention

L'élément sur lequel vous cliquez directement dans l'interface de gauche peut ne pas être l'élément réel, car sa taille et sa position peuvent se superposer à d'autres éléments. En général, lorsque plusieurs éléments se chevauchent, nous les affichons également dans la barre d'informations de droite. Vous pouvez faire défiler vers le haut ou le bas pour trouver celui dont vous avez réellement besoin. Vous pouvez également parcourir manuellement tous les éléments en appuyant sur la touche TAB dans l'interface de sélection de gauche.

Pour l'élément ci-dessus, nous le récupérons généralement via text. La condition pour utiliser text est qu'aucun autre élément sur l'interface actuelle n'ait également le texte "同意". C'est la méthode la plus simple. Vous pouvez également utiliser resourceId, mais notez que resourceId ne représente pas un ID unique, mais un ID de ressource, et une interface peut contenir de nombreux éléments avec le même ID de ressource. D'autres attributs comme packageName, checkable, etc., sont moins courants, mais peuvent être utilisés si text, resourceId, description, etc., ne sont pas disponibles. Nous pouvons obtenir cet élément des manières suivantes.

element = d(text="同意")
element = d(text="同意", resourceId="com.tencent.news:id/btm_first_agree")
element = d(resourceId="com.tencent.news:id/btm_first_agree")

Clic sur un élément

Appelez l'interface suivante pour effectuer un clic normal sur un élément. Dans le contexte, cela réalisera l'effet d'un clic manuel sur "Accepter".

element.click()

Si vous devez spécifier la position du clic sur l'élément, vous pouvez spécifier corner. Corner.COR_CENTER représente un clic au centre de l'élément. Vous pouvez également cliquer sur son coin supérieur gauche ou inférieur droit (COR_BOTTOMRIGHT).

element.click_exists(corner=Corner.COR_TOPLEFT)

Effectue un clic long sur l'élément. Lève une exception s'il n'existe pas. Cette interface prend également en charge corner, mais ne permet pas de spécifier la durée du clic long.

element.long_click()

Clique sur l'élément s'il existe. Si l'élément n'existe pas, l'appel à cette interface ne lèvera pas d'exception. Cette interface prend également en charge corner.

element.click_exists()
>>> element.click_exists()
True

Vérifier l'existence

Dans de nombreux cas, il est nécessaire de vérifier l'existence d'un élément avant de poursuivre les opérations. Sinon, le flux de travail pourrait rencontrer des exceptions ou effectuer des actions incorrectes sur la mauvaise interface. Vous devrez peut-être utiliser l'interface suivante pour vérifier l'existence dans certaines situations.

element.exists()

Informations sur l'élément

Dans certaines situations, vous pourriez vouloir obtenir des informations partielles sur un élément, telles que ses coordonnées, sa zone, ou les chaînes de caractères qu'il contient comme le texte ou la description. Vous pouvez utiliser l'interface suivante pour lire les informations de l'élément.

element.info()

Pour notre élément de test ci-dessus, les informations affichées sont :

>>> info = element.info()
>>> print (info)
bounds { ... }
className: "android.widget.TextView"
clickable: true
enabled: true
focusable: true
packageName: "com.tencent.news"
resourceName: "com.tencent.news:id/btn_first_agree"
text: "\345\220\214\346\204\217"
visibleBounds { ... }

Astuce

Vous remarquerez peut-être que certaines informations, comme `description`, sont absentes dans la sortie ci-dessus. Cela signifie généralement que le champ est vide ou `false`. Vous pouvez toujours accéder à ces champs via leurs attributs pour obtenir leur valeur.

Comme vous pouvez le voir, ces informations sont un peu complexes. C'est le format d'affichage par défaut de protobuf. Vous pouvez accéder directement aux attributs correspondants pour afficher leurs valeurs réelles. Par exemple, pour lire la valeur du text de l'élément, vous pouvez l'utiliser comme suit.

>>> info = element.info()
>>> print (info.text)
同意

Bien sûr, il y a aussi des informations sur les coordonnées de la zone de l'élément, auxquelles vous pouvez également accéder. Par exemple, si vous voulez obtenir les informations sur la zone de l'élément, vous pouvez les afficher comme suit, ou les stocker dans une variable pour des opérations ultérieures.

>>> info = element.info()
>>> print (info.bounds)

La valeur de sortie ou de retour est une information de zone (Bound). Vous découvrirez plus tard que c'est un paramètre également utilisé par une certaine interface de capture d'écran. Oui, vous pouvez passer ce paramètre à l'interface de capture d'écran pour prendre une capture d'écran de cet élément seul, mais nous l'avons déjà encapsulé pour vous.

Vous pourriez également vouloir obtenir la largeur et la hauteur de l'élément pour calculer certains décalages, comme le décalage par rapport à d'autres éléments. Vous pouvez le faire comme ceci.

>>> info = element.info()
>>> print (info.bounds.width, info.bounds.height)
484 138

Ou, obtenir le point central de l'élément, ou les points de coin comme le coin supérieur gauche ou inférieur droit. Bien sûr, les interfaces suivantes retournent généralement des informations de type Point, et vous pouvez obtenir les coordonnées X et Y de l'écran de l'appareil à partir de l'objet Point.

>>> info = element.info()
>>> print (info.bounds.center())
x: 792
y: 1908
>>> print (info.bounds.center().x)
792

L'appel suivant est utilisé pour obtenir les coordonnées des coins de l'élément. L'exemple obtient les coordonnées du coin supérieur gauche. Il prend également en charge l'obtention des coordonnées des quatre coins, tels que bottom-right, top-right, et bottom-left.

>>> info = element.info()
>>> print (info.bounds.corner("top-left"))
x: 550
y: 1839
>>> print (info.bounds.corner("top-left").x)
550

Parcourir les éléments

Vous pouvez également parcourir tous les éléments sélectionnés par le sélecteur. Normalement, il se peut qu'il n'y ait qu'un seul élément dans le contexte, donc si vous testez, veuillez choisir un autre sélecteur pour vos tests. Vous pouvez utiliser une boucle for ou d'autres méthodes directement sur le sélecteur pour le parcourir.

for i in element: print (i)

Ou si vous savez qu'il y a plusieurs éléments correspondants et que vous voulez obtenir le N-ième élément, vous pouvez utiliser l'interface suivante.

element_3rd = element.get(3)

Compter les éléments

En général, vous n'utiliserez pas directement cette interface. L'appel suivant peut obtenir le nombre d'éléments correspondant à votre sélecteur actuel.

>>> element.count()
1

Capture d'écran d'un élément

Nous prenons en charge les captures d'écran au niveau de l'élément, vous permettant de capturer l'image d'un élément individuel sans avoir à faire une capture d'écran complète puis à la recadrer.

element.screenshot(quality=60)

Après avoir pris la capture d'écran, vous pouvez utiliser getvalue pour obtenir les données binaires de la capture, ou la passer directement à une PIL Image.

>>> element.screenshot(quality=60).getvalue()
b'\xff\xd8\xff\xe0\x00\x10JFIF\x00\x01\x01\x00\x00\x01\x00\x01\x00\x00\xff\xe2\x02(ICC_PROFILE\x00\x01\x01\x00\x00\x02\x18\x00\x00\x00\x00\x02\x10\x00\x00mntrRGB XYZ \x00\x00...

Ou, si vous n'avez pas besoin de traitement supplémentaire, vous pouvez choisir de sauvegarder directement la capture d'écran dans un fichier local.

>>> element.screenshot(quality=60).save("image.png")

Attendre un élément

Dans certaines situations, vous devrez peut-être déterminer si la page actuelle a fini de se charger. En général, vous pouvez le faire en vérifiant si un élément pertinent est déjà affiché. L'exemple suivant attendra que l'élément "同意" apparaisse, avec un temps d'attente maximum de 10 secondes.

Astuce

La durée d'attente ici est en millisecondes, donc 10 secondes doivent être multipliées par 1000. 10 secondes = 10000 millisecondes.
element.wait_for_exists(10*1000)
>>> element.wait_for_exists(10*1000)
True

Bien sûr, nous ne prenons pas seulement en charge l'attente de l'apparition d'un élément, mais aussi l'attente de sa disparition, c'est-à-dire jusqu'à ce que l'élément disparaisse de l'interface.

element.wait_until_gone(10*1000)
>>> element.wait_until_gone(10*1000)
False

Saisie de texte

La saisie de texte est un point qui nécessite une attention particulière. Nous ne pouvons pas saisir de texte dans un bouton "Accepter" car c'est un bouton. Prenons maintenant un élément de champ de saisie comme exemple. Les informations de base de cet élément sont présentées ci-dessous.

Saisie de texte

Attention

Il y a quelques points à noter lors de l'obtention d'un élément de champ de saisie. Assurez-vous que votre méthode de saisie est **affichée** avant de rechercher l'élément pertinent, et nous vous recommandons de chercher attentivement, sinon vous risquez de ne pas obtenir le véritable champ de saisie.

Astuce

Dans le flux de votre code d'automatisation, pour faire apparaître la méthode de saisie, il vous suffit d'écrire du code pour cliquer d'abord sur le champ de saisie parent affiché.

Pour le champ de saisie ci-dessus, nous pouvons appeler l'interface suivante pour y saisir la chaîne "你好世界" (Bonjour le monde). Bien sûr, la saisie de chaînes en anglais ou d'autres chaînes Unicode est également prise en charge. Il vous suffit de l'utiliser comme suit pour saisir du texte dans le champ.

>>> element = d(text="搜索感兴趣的内容")
>>> element.set_text("你好世界")
True

Ou, si vous avez soudainement envie d'obtenir le texte actuellement affiché dans ce champ de saisie, vous pouvez l'appeler comme ceci.

Attention

Vous pouvez voir que nous avons changé de sélecteur ici. Notre sélecteur initial était basé sur `text`, mais après avoir saisi du texte, le contenu a changé, donc l'élément n'existe plus sous ce sélecteur. Nous en avons donc utilisé un autre. Il est très important d'utiliser des sélecteurs appropriés, mais puisque c'est déjà écrit, laissons-le comme ça.
>>> element = d(className="android.widget.EditText")
>>> element.get_text()
'你好世界'

Ou encore, pour effacer le contenu actuellement saisi. Normalement, la saisie de texte efface automatiquement le texte précédent, mais vous pouvez également l'effacer manuellement.

Astuce

En fait, un effet similaire peut être obtenu en utilisant l'interface des touches pour appuyer de manière répétée sur la touche RETOUR ARRIÈRE.
>>> element = d(className="android.widget.EditText")
>>> element.clear_text_field( )
True

Remarque

Dans des cas extrêmes, il se peut que cette interface ne fonctionne pas correctement pour la saisie de texte dans certains champs. Nous travaillons à améliorer sa prise en charge.

Défilement normal

Utilisez l'interface suivante pour effectuer des opérations de défilement sur l'interface, comme faire défiler une liste vers le haut ou le bas pour changer de page. L'appel suivant réalise un défilement vers le haut. Ajustez step vous-même ; plus la valeur est grande, plus la vitesse de défilement sera lente, ce qui convient aux défilements nécessitant une plus grande précision.

Attention

Par paresse, vous pouvez omettre le paramètre de sélecteur pour cette opération, mais si vous rencontrez des problèmes de défilement, veuillez définir vous-même les conditions du sélecteur sur un élément approprié, tel qu'un élément avec l'attribut `scrollable` ou le conteneur de premier niveau d'une liste.
d().swipe(direction=Direction.DIR_UP, step=32)
>>> element = d(resourceId="com.tencent.news:id/important_list_content")
>>> element.swipe(direction=Direction.DIR_UP, step=32)
True
Indicateur de directionDescription
Direction.DIR_UPDéfilement vers le haut
Direction.DIR_LEFTDéfilement vers la gauche
Direction.DIR_DOWNDéfilement vers le bas
Direction.DIR_RIGHTDéfilement vers la droite

Défilement rapide

Le défilement rapide (fling) simule le comportement d'un utilisateur balayant rapidement l'écran. Cette opération fait défiler l'écran rapidement et convient à la simulation d'actions de navigation rapide. L'exemple suivant fait défiler l'écran de haut en bas. Dans l'exemple, le sélecteur est vide, mais vous devrez peut-être le spécifier en fonction de la situation.

d().fling_from_top_to_bottom()

Défilement rapide de bas en haut

d().fling_from_bottom_to_top()

Défilement rapide de gauche à droite

d().fling_from_left_to_right()

Défilement rapide de droite à gauche

d().fling_from_right_to_left()

Attention

Par paresse, vous pouvez omettre le paramètre de sélecteur pour cette opération, mais si vous rencontrez des problèmes de défilement, veuillez définir vous-même les conditions du sélecteur sur un élément approprié, tel qu'un élément avec l'attribut `scrollable` ou le conteneur de premier niveau d'une liste.
>>> element = d(resourceId="com.tencent.news:id/important_list_content")
>>> element.fling_from_bottom_to_top()
True

Mise à jour en cours...

Autres opérations

# Faire glisser cette application dans le dossier "Shopping" (à modifier selon la situation réelle)
element.drag_to(Selector(text="购物"))

#########
# Trouver des éléments frères ou enfants
#########
# Parfois, il y a des éléments en double ou sans caractéristiques distinctives, ce qui les rend difficiles à localiser
# Dans ce cas, vous pouvez réduire la portée de la recherche en trouvant des éléments enfants/frères
# Élément enfant, par exemple : dans une boîte de dialogue de connexion de chat, les champs de saisie sont des éléments enfants de la boîte de dialogue
# Élément frère, par exemple : dans une boîte de dialogue de connexion, les champs nom d'utilisateur et mot de passe sont des éléments frères (normalement)
form = d(resourceId="login_form")
form.child(index=1)
# Ceci obtiendra l'élément à l'index 0 sous login_form
form.child(index=1).sibling()
# Vous pouvez également trouver le bouton "Mot de passe oublié" qui est un frère de login_form de cette manière
# (En réalité, cela peut déjà être fait en se basant sur la chaîne de caractères, donc ce n'est pas nécessaire, c'est juste pour la démonstration)
form.sibling(textContains="找回密码")
# Ce sont eux-mêmes des éléments, vous pouvez effectuer n'importe quelle opération d'élément sur eux


# Autres, faire défiler continuellement vers le bas/gauche/droite/haut jusqu'à la fin
# Comme il n'est pas toujours possible de faire défiler jusqu'à la fin ou de détecter la fin du défilement
# le paramètre max_swipes est obligatoire
d().fling_from_top_to_bottom_to_end(max_swipes=32)
d().fling_from_bottom_to_top_to_end(max_swipes=32)
d().fling_from_left_to_right_to_end(max_swipes=32)
d().fling_from_right_to_left_to_end(max_swipes=32)

#########
# scroll: un défilement plus mécanique
#########
step = 60
max_swipes = 32
# Faire défiler de haut en bas de 'step' pas
d().scroll_from_top_to_bottom(step)
# Faire défiler de bas en haut de 'step' pas
d().scroll_from_bottom_to_top(step)
# Faire défiler de gauche à droite de 'step' pas
d().scroll_from_left_to_right(step)
# Faire défiler de droite à gauche de 'step' pas
d().scroll_from_right_to_left(step)

# Autres, faire défiler continuellement vers le bas/gauche/droite/haut jusqu'à la fin
# Identique à la description de fling ci-dessus
d().scroll_from_top_to_bottom_to_end(max_swipes, step)
d().scroll_from_bottom_to_top_to_end(max_swipes, step)
d().scroll_from_left_to_right_to_end(max_swipes, step)
d().scroll_from_right_to_left_to_end(max_swipes, step)