Je vais garder l'opinion impopulaire sur le tag SO selenium que XPath est préférable à la CSS à long terme.
Ce long billet se divise en deux parties : d'abord, je vais prouver, à l'aide d'une méthode approximative, que la différence de performance entre les deux est de 1,5 million d'euros. 0,1-0,3 millisecondes (oui, c'est 100 micro secondes) Puis je vous dirai pourquoi XPath est plus puissant.
Différence de performance
Commençons par aborder "l'éléphant dans la pièce", à savoir que xpath est plus lent que css.
Avec la puissance actuelle des processeurs (lire : tout x86 produit depuis 2013) même sur des VMs browserstack/saucelabs/aws, et le développement des navigateurs (lire : tous les films populaires des 5 dernières années) c'est loin d'être le cas. Les moteurs des navigateurs ont évolué, le support de xpath est uniforme, IE n'est plus dans le coup (espérons-le pour la plupart d'entre nous) . Cette comparaison dans l'autre réponse est citée un peu partout, mais elle est très contextuelle - combien de personnes exécutent - ou se soucient - de l'automatisation contre IE8 ?
S'il y a une différence, c'est dans une fraction de milliseconde .
Pourtant, la plupart des frameworks de niveau supérieur ajoutent au moins 1 ms de surcharge par rapport à l'appel brut de selenium (wrappers, handlers, stockage d'état, etc.) ; mon arme personnelle de choix - RobotFramework - ajoute au moins 2 ms, que je suis plus qu'heureux de sacrifier pour ce qu'elle fournit. Un aller-retour réseau d'un AWS us-east-1 au hub de BrowserStack est généralement de 11 millisecondes .
Ainsi, avec les navigateurs distants, s'il existe une différence entre xpath et css, elle est éclipsée par tout le reste, en ordres de grandeur.
Les mesures
Il n'y a pas beaucoup de comparaisons publiques (Je n'ai vraiment vu que celui qui est cité) Voici donc un cas unique, factice et simple.
Il va localiser un élément par les deux stratégies X fois, et comparer le temps moyen pour cela.
La cible - la page d'accueil de BrowserStack, et son bouton "Sign Up" ; une capture d'écran du code html au moment de la rédaction de cet article :
Voici le code de test (python) :
from selenium import webdriver
import timeit
if __name__ == '__main__':
xpath_locator = '//div[@class="button-section col-xs-12 row"]'
css_locator = 'div.button-section.col-xs-12.row'
repetitions = 1000
driver = webdriver.Chrome()
driver.get('https://www.browserstack.com/')
css_time = timeit.timeit("driver.find_element_by_css_selector(css_locator)",
number=repetitions, globals=globals())
xpath_time = timeit.timeit('driver.find_element_by_xpath(xpath_locator)',
number=repetitions, globals=globals())
driver.quit()
print("css total time {} repeats: {:.2f}s, per find: {:.2f}ms".
format(repetitions, css_time, (css_time/repetitions)*1000))
print("xpath total time for {} repeats: {:.2f}s, per find: {:.2f}ms".
format(repetitions, xpath_time, (xpath_time/repetitions)*1000))
Pour ceux qui ne sont pas familiers avec Python - il ouvre la page, et trouve l'élément - d'abord avec le localisateur css, puis avec le xpath ; l'opération de recherche est répétée 1.000 fois. La sortie est le temps total en secondes pour les 1 000 répétitions, et le temps moyen pour une recherche en millisecondes.
Les localisateurs sont :
- pour xpath - "un élément div ayant cette valeur de classe exacte, quelque part dans le DOM" ;
- le css est similaire - "un élément div avec cette classe, quelque part dans le DOM".
Délibérément choisi pour ne pas être surajouté ; aussi, le sélecteur de classe est cité pour le css comme "le deuxième plus rapide après un id".
L'environnement - Chrome v66.0.3359.139, chromedriver v2.38, cpu : ULV Core M-5Y10 fonctionnant habituellement à 1.5GHz (oui, un "traitement de texte", même pas une bête i7 normale) .
Voici le résultat :
css total time 1000 repeats: 8.84s, per find: 8.84ms
xpath total time for 1000 repeats: 8.52s, per find: 8.52ms
De toute évidence, les temps de recherche sont assez proches ; la différence est la suivante 0.32 millisecondes . Ne sautez pas sur "le xpath est plus rapide" - parfois c'est le cas, parfois c'est le css.
Essayons avec un autre ensemble de localisateurs, un peu plus compliqué - un attribut ayant une sous-chaîne (approche courante, du moins pour moi, qui consiste à s'en prendre à la classe d'un élément lorsqu'une partie de celui-ci a une signification fonctionnelle). :
xpath_locator = '//div[contains(@class, "button-section")]'
css_locator = 'div[class~=button-section]'
Les deux localisateurs sont sémantiquement identiques - "trouver un élément div ayant dans son attribut class cette sous-chaîne".
Voici les résultats :
css total time 1000 repeats: 8.60s, per find: 8.60ms
xpath total time for 1000 repeats: 8.75s, per find: 8.75ms
Diff de 0.15ms .
À titre d'exercice, le même test que celui effectué dans le cadre de l'enquête sur la santé des femmes. blog lié dans les commentaires/autre réponse - le page de test est public, tout comme le code de test .
Ils font plusieurs choses dans le code - cliquer sur une colonne pour la trier, puis obtenir les valeurs, et vérifier que le tri de l'interface utilisateur est correct.
Je vais le couper - il suffit de prendre les localisateurs, après tout - c'est le test Root, non ?
Le même code que ci-dessus, avec ces modifications :
-
L'url est maintenant http://the-internet.herokuapp.com/tables
; il y a 2 tests.
-
Les localisateurs pour le premier - "Finding Elements By ID and Class" - sont les suivants :
css_locator = '#table2 tbody .dues'
xpath_locator = "//table[@id='table2']//tr/td[contains(@class,'dues')]"
Et voici le résultat :
css total time 1000 repeats: 8.24s, per find: 8.24ms
xpath total time for 1000 repeats: 8.45s, per find: 8.45ms
Diff de 0.2 millisecondes.
La "recherche d'éléments par parcours" :
css_locator = '#table1 tbody tr td:nth-of-type(4)'
xpath_locator = "//table[@id='table1']//tr/td[4]"
Le résultat :
css total time 1000 repeats: 9.29s, per find: 9.29ms
xpath total time for 1000 repeats: 8.79s, per find: 8.79ms
Cette fois, c'est 0.5 ms (en sens inverse, xpath s'est avéré plus "rapide" ici).
Donc 5 ans plus tard (meilleurs moteurs de navigation) et Si l'on se concentre uniquement sur les performances des localisateurs (pas d'actions comme le tri dans l'interface utilisateur, etc.), avec le même banc d'essai, il n'y a pratiquement aucune différence entre CSS et XPath.
Donc, entre xpath et css, lequel des deux choisir pour les performances ? La réponse est simple : choisissez localisation par identification .
Pour faire court, si l'identifiant d'un élément est unique (comme il est censé l'être selon les spécifications), sa valeur joue un rôle important dans la représentation interne du DOM par le navigateur, et est donc généralement la plus rapide.
Pourtant, unique et constant (par exemple, non généré automatiquement) Les identifiants ne sont pas toujours disponibles, ce qui nous amène à la question "pourquoi XPath s'il y a CSS ?".
L'avantage de XPath
Sans parler des performances, pourquoi je pense que xpath est meilleur ? C'est simple : la polyvalence et la puissance.
Xpath est un langage développé pour travailler avec des documents XML ; en tant que tel, il permet des constructions beaucoup plus puissantes que css.
Par exemple, la navigation dans toutes les directions de l'arbre - trouver un élément, puis aller à son grand-parent et chercher un enfant de celui-ci ayant certaines propriétés.
Il permet d'intégrer des conditions booléennes - cond1 and not(cond2 or not(cond3 and cond4))
; sélecteurs intégrés - "trouver un div ayant ces enfants avec ces attributs, puis naviguer en fonction de celui-ci".
XPath permet d'effectuer des recherches sur la base de la valeur d'un nœud (son texte) - même si cette pratique est mal vue, elle s'avère utile, notamment dans les documents mal structurés. (pas d'attributs définis sur lesquels s'appuyer, comme les ids et les classes dynamiques - localisez l'élément par son contenu textuel) .
Le démarrage en css est définitivement plus facile - on peut commencer à écrire des sélecteurs en quelques minutes ; mais après quelques jours d'utilisation, la puissance et les possibilités offertes par xpath l'emportent rapidement sur css.
Et purement subjectif - un css complexe est beaucoup plus difficile à lire qu'une expression xpath complexe.
Outro ;)
Enfin, encore une fois très subjectif, lequel choisir ?
Il n'y a pas de bon ou de mauvais choix - ce sont des solutions différentes au même problème, et il faut choisir celle qui convient le mieux à la situation.
Étant un "fan" de XPath, je n'hésite pas à utiliser dans mes projets un mélange des deux. Parfois, il est beaucoup plus rapide de lancer un CSS, si je sais qu'il fera parfaitement l'affaire.