Dans un précédent article j’ai expliqué comment choisir la meilleure stratégie de localisation webdriver en fonction du contexte du projet.
En revanche il manquait des données statistiques Css Vs.Xpath pour réduire la propagation du bruit 😛
Et justement pour trouver les données j’ai effectué plusieurs recherches sur internet … Malheureusement aucune source fiable, claire à l’exception d’un ancien benchmark de Dave Haeffner, mais les données ne sont pas à jour depuis des années !.
J’ai donc décidé de faire un benchmark pour mesurer la performance des sélecteurs Web Css et Xpath pour plusieurs navigateurs et sur plusieurs plateformes.
Comme tout benchmark la préparation du contexte est un élément essentiel pour obtenir de bons résultats.
Pour réaliser ce travail, je me suis servi de plusieurs idées provenant de l’ancien benchmark de Dave Haeffner notamment pour le choix des sélecteurs css/xpath et aussi pour la page web de test qui sera utilisée par ce benchmark.
Cette page à été développée par Dave pour réaliser son benchmark à l’époque, elle contient une structure HTML particulièrement intéressante (page large et profonde) pour faire des tests comparatifs css vs xpath sur plusieurs navigateurs …
Le principe de ce benchmark est simple, une fois la page de test est chargée par le navigateur, on exécute la commande selenium await driver.findElement(locator)
plusieurs fois avec plusieurs stratégies css, xpath et on mesure pour chaque stratégie le nombre d’opérations par seconde.
Et pour obtenir les meilleurs mesures possible je me suis servi du benchmarkjs un outil de benchmarking en javascript très populaire et possède un algorithme qui calcul automatiquement le nombre des itérations nécessaires pour faire un test et exécute également des tests à vide pour assurer une certaine stabilité avant de lancer le benchmark.
La page sous test n’est qu’une version locale de la page disponible ici , elle est servie localement via le framework expressjs.
Un dernier point important, le benchmark est exécuté sur des machines virtuelles similaires (configuration hardware similaire) sur la plateforme Github Actions.
Cette configuration nous permet d’éviter les effets de bord notamment la latence de la transmission des données via internet etc.
Plusieurs localisateurs css, xpath on été utilisés (ce sont les même localisateurs de Dave), le choix est bien étudié, on retrouve des localisateurs simples (ID, class, etc.), mais aussi des localisateurs complexes pour traverser entièrement la page ….
Je vous donne ici un exemple, mais attention il ne faut pas utiliser ce type de localisateurs dans vos projets c’est fragile, n’hésitez pas de regarder cet article pour savoir comment choisir la meilleure stratégie possible
div#siblings > div:nth-of-type(1) > div:nth-of-type(3) > div:nth-of-type(3) > div:nth-of-type(3) > div:nth-of-type(3) > div:nth-of-type(3) > div:nth-of-type(3) > div:nth-of-type(3) > div:nth-of-type(3) > div:nth-of-type(3) > div:nth-of-type(3) > div:nth-of-type(3) > div:nth-of-type(3) > div:nth-of-type(3) > div:nth-of-type(3) > div:nth-of-type(3) > div:nth-of-type(3) > div:nth-of-type(3) > div:nth-of-type(3) > div:nth-of-type(3) > div:nth-of-type(3) > div:nth-of-type(3) > div:nth-of-type(3) > div:nth-of-type(3) > div:nth-of-type(3) > div:nth-of-type(3) > div:nth-of-type(3) > div:nth-of-type(3) > div:nth-of-type(3) > div:nth-of-type(3) > div:nth-of-type(3) > div:nth-of-type(3) > div:nth-of-type(3) > div:nth-of-type(3) > div:nth-of-type(3) > div:nth-of-type(3) > div:nth-of-type(3) > div:nth-of-type(3) > div:nth-of-type(3) > div:nth-of-type(3) > div:nth-of-type(3) > div:nth-of-type(3) > div:nth-of-type(3) > div:nth-of-type(3) > div:nth-of-type(3) > div:nth-of-type(3) > div:nth-of-type(3) > div:nth-of-type(3) > div:nth-of-type(3) > div:nth-of-type(3)
Option | Description |
---|---|
Locator 1 | nested sibling traversal |
Locator 2 | nested sibling traversal by class |
Locator 3 | table header id_and_class |
Locator 4 | table header id class and direct desc |
Locator 5 | table header traversing |
Locator 6 | table header traversing and direct desc |
Locator 7 | table cell id and_class |
Locator 8 | table cell id class and direct desc |
Locator 9 | table cell traversing |
Locator 10 | table cell traversing and direct desc |
Rapport graphique
Log benchmark-js
css => nested_sibling_traversal x 139 ops/sec ±8.44% (72 runs sampled)
xpath => nested_sibling_traversal x 132 ops/sec ±1.78% (78 runs sampled)
css => nested_sibling_traversal_by_class x 153 ops/sec ±1.53% (80 runs sampled)
xpath => nested_sibling_traversal_by_class x 98.61 ops/sec ±1.58% (77 runs sampled)
css => table_header_id_and_class x 157 ops/sec ±1.49% (81 runs sampled)
xpath => table_header_id_and_class x 139 ops/sec ±1.47% (81 runs sampled)
css => table_header_id_class_and_direct_desc x 158 ops/sec ±1.19% (82 runs sampled)
xpath => table_header_id_class_and_direct_desc x 142 ops/sec ±1.26% (83 runs sampled)
css => table_header_traversing x 158 ops/sec ±1.41% (82 runs sampled)
xpath => table_header_traversing x 139 ops/sec ±1.51% (81 runs sampled)
css => table_header_traversing_and_direct_desc x 158 ops/sec ±1.36% (82 runs sampled)
xpath => table_header_traversing_and_direct_desc x 141 ops/sec ±1.17% (82 runs sampled)
css => table_cell_id_and_class x 159 ops/sec ±1.06% (83 runs sampled)
xpath => table_cell_id_and_class x 111 ops/sec ±1.56% (75 runs sampled)
css => table_cell_id_class_and_direct_desc x 159 ops/sec ±1.35% (81 runs sampled)
xpath => table_cell_id_class_and_direct_desc x 114 ops/sec ±1.62% (77 runs sampled)
css => table_cell_traversing x 162 ops/sec ±1.37% (82 runs sampled)
xpath => table_cell_traversing x 104 ops/sec ±1.87% (76 runs sampled)
css => table_cell_traversing_and_direct_desc x 161 ops/sec ±1.44% (77 runs sampled)
xpath => table_cell_traversing_and_direct_desc x 123 ops/sec ±1.78% (73 runs sampled)
css => nested_sibling_traversal x 156 ops/sec ±2.04% (77 runs sampled)
xpath => nested_sibling_traversal x 144 ops/sec ±5.36% (75 runs sampled)
css => nested_sibling_traversal_by_class x 185 ops/sec ±1.55% (78 runs sampled)
xpath => nested_sibling_traversal_by_class x 103 ops/sec ±2.30% (74 runs sampled)
css => table_header_id_and_class x 192 ops/sec ±1.34% (80 runs sampled)
xpath => table_header_id_and_class x 155 ops/sec ±1.64% (72 runs sampled)
css => table_header_id_class_and_direct_desc x 175 ops/sec ±2.00% (81 runs sampled)
xpath => table_header_id_class_and_direct_desc x 156 ops/sec ±1.63% (79 runs sampled)
css => table_header_traversing x 181 ops/sec ±3.12% (76 runs sampled)
xpath => table_header_traversing x 148 ops/sec ±1.70% (76 runs sampled)
css => table_header_traversing_and_direct_desc x 180 ops/sec ±1.52% (79 runs sampled)
xpath => table_header_traversing_and_direct_desc x 154 ops/sec ±1.28% (79 runs sampled)
css => table_cell_id_and_class x 182 ops/sec ±1.18% (79 runs sampled)
xpath => table_cell_id_and_class x 123 ops/sec ±1.92% (72 runs sampled)
css => table_cell_id_class_and_direct_desc x 180 ops/sec ±1.50% (76 runs sampled)
xpath => table_cell_id_class_and_direct_desc x 118 ops/sec ±3.40% (72 runs sampled)
css => table_cell_traversing x 171 ops/sec ±1.94% (79 runs sampled)
xpath => table_cell_traversing x 116 ops/sec ±1.66% (77 runs sampled)
css => table_cell_traversing_and_direct_desc x 174 ops/sec ±2.15% (80 runs sampled)
xpath => table_cell_traversing_and_direct_desc x 136 ops/sec ±2.34% (79 runs sampled)
css => nested_sibling_traversal x 174 ops/sec ±6.86% (68 runs sampled)
xpath => nested_sibling_traversal x 160 ops/sec ±1.35% (72 runs sampled)
css => nested_sibling_traversal_by_class x 192 ops/sec ±1.37% (73 runs sampled)
xpath => nested_sibling_traversal_by_class x 114 ops/sec ±2.57% (71 runs sampled)
css => table_header_id_and_class x 197 ops/sec ±0.78% (75 runs sampled)
xpath => table_header_id_and_class x 171 ops/sec ±1.00% (73 runs sampled)
css => table_header_id_class_and_direct_desc x 198 ops/sec ±1.19% (72 runs sampled)
xpath => table_header_id_class_and_direct_desc x 166 ops/sec ±1.37% (70 runs sampled)
css => table_header_traversing x 203 ops/sec ±0.77% (76 runs sampled)
xpath => table_header_traversing x 170 ops/sec ±1.31% (70 runs sampled)
css => table_header_traversing_and_direct_desc x 200 ops/sec ±0.69% (75 runs sampled)
xpath => table_header_traversing_and_direct_desc x 172 ops/sec ±1.23% (71 runs sampled)
css => table_cell_id_and_class x 202 ops/sec ±0.84% (74 runs sampled)
xpath => table_cell_id_and_class x 128 ops/sec ±1.46% (70 runs sampled)
css => table_cell_id_class_and_direct_desc x 206 ops/sec ±0.72% (75 runs sampled)
xpath => table_cell_id_class_and_direct_desc x 130 ops/sec ±1.32% (68 runs sampled)
css => table_cell_traversing x 204 ops/sec ±0.87% (77 runs sampled)
xpath => table_cell_traversing x 120 ops/sec ±1.84% (72 runs sampled)
css => table_cell_traversing_and_direct_desc x 205 ops/sec ±0.71% (77 runs sampled)
xpath => table_cell_traversing_and_direct_desc x 151 ops/sec ±1.41% (70 runs sampled)
css => nested_sibling_traversal x 356 ops/sec ±4.82% (74 runs sampled)
xpath => nested_sibling_traversal x 347 ops/sec ±3.88% (78 runs sampled)
css => nested_sibling_traversal_by_class x 424 ops/sec ±3.74% (80 runs sampled)
xpath => nested_sibling_traversal_by_class x 144 ops/sec ±10.40% (78 runs sampled)
css => table_header_id_and_class x 460 ops/sec ±4.26% (79 runs sampled)
xpath => table_header_id_and_class x 403 ops/sec ±3.73% (80 runs sampled)
css => table_header_id_class_and_direct_desc x 474 ops/sec ±4.29% (82 runs sampled)
xpath => table_header_id_class_and_direct_desc x 431 ops/sec ±3.47% (80 runs sampled)
css => table_header_traversing x 481 ops/sec ±4.07% (79 runs sampled)
xpath => table_header_traversing x 396 ops/sec ±5.16% (81 runs sampled)
css => table_header_traversing_and_direct_desc x 470 ops/sec ±4.29% (80 runs sampled)
xpath => table_header_traversing_and_direct_desc x 411 ops/sec ±4.91% (77 runs sampled)
css => table_cell_id_and_class x 494 ops/sec ±1.59% (82 runs sampled)
xpath => table_cell_id_and_class x 300 ops/sec ±1.34% (84 runs sampled)
css => table_cell_id_class_and_direct_desc x 511 ops/sec ±1.36% (84 runs sampled)
xpath => table_cell_id_class_and_direct_desc x 312 ops/sec ±1.32% (85 runs sampled)
css => table_cell_traversing x 509 ops/sec ±1.46% (80 runs sampled)
xpath => table_cell_traversing x 290 ops/sec ±1.28% (83 runs sampled)
css => table_cell_traversing_and_direct_desc x 520 ops/sec ±1.43% (84 runs sampled)
xpath => table_cell_traversing_and_direct_desc x 420 ops/sec ±4.66% (83 runs sampled)
css => nested_sibling_traversal x 350 ops/sec ±8.12% (72 runs sampled)
xpath => nested_sibling_traversal x 347 ops/sec ±3.56% (78 runs sampled)
css => nested_sibling_traversal_by_class x 437 ops/sec ±4.55% (78 runs sampled)
xpath => nested_sibling_traversal_by_class x 140 ops/sec ±2.69% (78 runs sampled)
css => table_header_id_and_class x 445 ops/sec ±4.22% (76 runs sampled)
xpath => table_header_id_and_class x 382 ops/sec ±3.40% (76 runs sampled)
css => table_header_id_class_and_direct_desc x 474 ops/sec ±4.42% (77 runs sampled)
xpath => table_header_id_class_and_direct_desc x 420 ops/sec ±3.59% (75 runs sampled)
css => table_header_traversing x 445 ops/sec ±3.71% (78 runs sampled)
xpath => table_header_traversing x 371 ops/sec ±4.41% (76 runs sampled)
css => table_header_traversing_and_direct_desc x 447 ops/sec ±4.69% (76 runs sampled)
xpath => table_header_traversing_and_direct_desc x 397 ops/sec ±1.95% (77 runs sampled)
css => table_cell_id_and_class x 460 ops/sec ±2.30% (81 runs sampled)
xpath => table_cell_id_and_class x 277 ops/sec ±1.69% (80 runs sampled)
css => table_cell_id_class_and_direct_desc x 418 ops/sec ±7.28% (71 runs sampled)
xpath => table_cell_id_class_and_direct_desc x 292 ops/sec ±2.51% (79 runs sampled)
css => table_cell_traversing x 488 ops/sec ±3.12% (80 runs sampled)
xpath => table_cell_traversing x 262 ops/sec ±1.40% (81 runs sampled)
css => table_cell_traversing_and_direct_desc x 430 ops/sec ±17.77% (71 runs sampled)
xpath => table_cell_traversing_and_direct_desc x 189 ops/sec ±30.31% (46 runs sampled)
css => nested_sibling_traversal x 262 ops/sec ±5.21% (61 runs sampled)
xpath => nested_sibling_traversal x 202 ops/sec ±7.48% (56 runs sampled)
css => nested_sibling_traversal_by_class x 217 ops/sec ±5.19% (62 runs sampled)
xpath => nested_sibling_traversal_by_class x 76.43 ops/sec ±19.41% (54 runs sampled)
css => table_header_id_and_class x 311 ops/sec ±5.94% (60 runs sampled)
xpath => table_header_id_and_class x 290 ops/sec ±3.93% (63 runs sampled)
css => table_header_id_class_and_direct_desc x 308 ops/sec ±4.52% (58 runs sampled)
xpath => table_header_id_class_and_direct_desc x 350 ops/sec ±4.79% (58 runs sampled)
css => table_header_traversing x 345 ops/sec ±3.48% (57 runs sampled)
xpath => table_header_traversing x 260 ops/sec ±5.37% (61 runs sampled)
css => table_header_traversing_and_direct_desc x 326 ops/sec ±6.55% (59 runs sampled)
xpath => table_header_traversing_and_direct_desc x 261 ops/sec ±6.44% (56 runs sampled)
css => table_cell_id_and_class x 318 ops/sec ±14.41% (63 runs sampled)
xpath => table_cell_id_and_class x 228 ops/sec ±5.49% (60 runs sampled)
css => table_cell_id_class_and_direct_desc x 373 ops/sec ±4.20% (61 runs sampled)
xpath => table_cell_id_class_and_direct_desc x 247 ops/sec ±7.08% (50 runs sampled)
css => table_cell_traversing x 395 ops/sec ±7.69% (51 runs sampled)
xpath => table_cell_traversing x 212 ops/sec ±9.45% (60 runs sampled)
css => table_cell_traversing_and_direct_desc x 530 ops/sec ±3.74% (61 runs sampled)
xpath => table_cell_traversing_and_direct_desc x 377 ops/sec ±8.93% (50 runs sampled)
Linux not supported
css => nested_sibling_traversal x 165 ops/sec ±1.68% (80 runs sampled)
xpath => nested_sibling_traversal x 159 ops/sec ±1.80% (79 runs sampled)
css => nested_sibling_traversal_by_class x 198 ops/sec ±1.37% (82 runs sampled)
xpath => nested_sibling_traversal_by_class x 111 ops/sec ±1.60% (74 runs sampled)
css => table_header_id_and_class x 201 ops/sec ±1.42% (81 runs sampled)
xpath => table_header_id_and_class x 173 ops/sec ±1.48% (80 runs sampled)
css => table_header_id_class_and_direct_desc x 207 ops/sec ±1.42% (80 runs sampled)
xpath => table_header_id_class_and_direct_desc x 176 ops/sec ±1.25% (81 runs sampled)
css => table_header_traversing x 201 ops/sec ±1.29% (82 runs sampled)
xpath => table_header_traversing x 175 ops/sec ±1.67% (80 runs sampled)
css => table_header_traversing_and_direct_desc x 205 ops/sec ±1.20% (78 runs sampled)
xpath => table_header_traversing_and_direct_desc x 178 ops/sec ±1.90% (82 runs sampled)
css => table_cell_id_and_class x 201 ops/sec ±1.59% (78 runs sampled)
xpath => table_cell_id_and_class x 125 ops/sec ±7.14% (74 runs sampled)
css => table_cell_id_class_and_direct_desc x 206 ops/sec ±1.13% (79 runs sampled)
xpath => table_cell_id_class_and_direct_desc x 131 ops/sec ±2.08% (76 runs sampled)
css => table_cell_traversing x 201 ops/sec ±1.36% (80 runs sampled)
xpath => table_cell_traversing x 117 ops/sec ±2.00% (77 runs sampled)
css => table_cell_traversing_and_direct_desc x 203 ops/sec ±1.55% (79 runs sampled)
xpath => table_cell_traversing_and_direct_desc x 147 ops/sec ±2.04% (76 runs sampled)
css => nested_sibling_traversal x 147 ops/sec ±2.61% (69 runs sampled)
xpath => nested_sibling_traversal x 113 ops/sec ±10.29% (65 runs sampled)
css => nested_sibling_traversal_by_class x 134 ops/sec ±9.37% (58 runs sampled)
xpath => nested_sibling_traversal_by_class x 102 ops/sec ±2.13% (71 runs sampled)
css => table_header_id_and_class x 189 ops/sec ±1.07% (71 runs sampled)
xpath => table_header_id_and_class x 160 ops/sec ±1.64% (72 runs sampled)
css => table_header_id_class_and_direct_desc x 188 ops/sec ±1.55% (70 runs sampled)
xpath => table_header_id_class_and_direct_desc x 155 ops/sec ±1.51% (69 runs sampled)
css => table_header_traversing x 191 ops/sec ±1.44% (71 runs sampled)
xpath => table_header_traversing x 153 ops/sec ±1.82% (66 runs sampled)
css => table_header_traversing_and_direct_desc x 178 ops/sec ±6.21% (69 runs sampled)
xpath => table_header_traversing_and_direct_desc x 152 ops/sec ±2.05% (69 runs sampled)
css => table_cell_id_and_class x 191 ops/sec ±2.11% (71 runs sampled)
xpath => table_cell_id_and_class x 112 ops/sec ±2.01% (66 runs sampled)
css => table_cell_id_class_and_direct_desc x 177 ops/sec ±2.53% (60 runs sampled)
xpath => table_cell_id_class_and_direct_desc x 120 ops/sec ±2.13% (56 runs sampled)
css => table_cell_traversing x 183 ops/sec ±1.78% (57 runs sampled)
xpath => table_cell_traversing x 94.47 ops/sec ±4.05% (57 runs sampled)
css => table_cell_traversing_and_direct_desc x 193 ops/sec ±1.17% (56 runs sampled)
xpath => table_cell_traversing_and_direct_desc x 140 ops/sec ±1.73% (54 runs sampled)
css => nested_sibling_traversal x 267 ops/sec ±22.46% (71 runs sampled)
xpath => nested_sibling_traversal x 247 ops/sec ±14.10% (63 runs sampled)
css => nested_sibling_traversal_by_class x 145 ops/sec ±16.60% (36 runs sampled)
xpath => nested_sibling_traversal_by_class x 156 ops/sec ±14.84% (60 runs sampled)
css => table_header_id_and_class x 372 ops/sec ±2.14% (73 runs sampled)
xpath => table_header_id_and_class x 357 ops/sec ±0.75% (74 runs sampled)
css => table_header_id_class_and_direct_desc x 364 ops/sec ±12.31% (69 runs sampled)
xpath => table_header_id_class_and_direct_desc x 373 ops/sec ±3.05% (71 runs sampled)
css => table_header_traversing x 398 ops/sec ±0.70% (69 runs sampled)
xpath => table_header_traversing x 329 ops/sec ±9.59% (69 runs sampled)
css => table_header_traversing_and_direct_desc x 365 ops/sec ±5.18% (65 runs sampled)
xpath => table_header_traversing_and_direct_desc x 326 ops/sec ±9.83% (68 runs sampled)
css => table_cell_id_and_class x 356 ops/sec ±3.86% (70 runs sampled)
xpath => table_cell_id_and_class x 232 ops/sec ±4.65% (67 runs sampled)
css => table_cell_id_class_and_direct_desc x 349 ops/sec ±3.87% (69 runs sampled)
xpath => table_cell_id_class_and_direct_desc x 251 ops/sec ±4.13% (69 runs sampled)
css => table_cell_traversing x 349 ops/sec ±3.67% (74 runs sampled)
xpath => table_cell_traversing x 222 ops/sec ±4.97% (69 runs sampled)
css => table_cell_traversing_and_direct_desc x 349 ops/sec ±3.61% (71 runs sampled)
xpath => table_cell_traversing_and_direct_desc x 282 ops/sec ±4.20% (70 runs sampled)
css => nested_sibling_traversal x 11.95 ops/sec ±2.58% (59 runs sampled)
xpath => nested_sibling_traversal x 16.89 ops/sec ±2.87% (79 runs sampled)
css => nested_sibling_traversal_by_class x 12.08 ops/sec ±1.37% (59 runs sampled)
xpath => nested_sibling_traversal_by_class x 7.23 ops/sec ±1.49% (39 runs sampled)
css => table_header_id_and_class x 11.93 ops/sec ±1.44% (59 runs sampled)
xpath => table_header_id_and_class x 17.24 ops/sec ±1.03% (80 runs sampled)
css => table_header_id_class_and_direct_desc x 12.11 ops/sec ±1.27% (60 runs sampled)
xpath => table_header_id_class_and_direct_desc x 17.17 ops/sec ±1.20% (80 runs sampled)
css => table_header_traversing x 12.30 ops/sec ±1.20% (60 runs sampled)
xpath => table_header_traversing x 17.39 ops/sec ±0.65% (73 runs sampled)
css => table_header_traversing_and_direct_desc x 12.47 ops/sec ±1.05% (61 runs sampled)
xpath => table_header_traversing_and_direct_desc x 17.47 ops/sec ±0.90% (81 runs sampled)
css => table_cell_id_and_class x 12.31 ops/sec ±1.25% (61 runs sampled)
xpath => table_cell_id_and_class x 17.56 ops/sec ±0.84% (45 runs sampled)
css => table_cell_id_class_and_direct_desc x 12.40 ops/sec ±1.21% (61 runs sampled)
xpath => table_cell_id_class_and_direct_desc x 17.46 ops/sec ±0.95% (47 runs sampled)
css => table_cell_traversing x 12.36 ops/sec ±1.47% (61 runs sampled)
xpath => table_cell_traversing x 10.77 ops/sec ±1.45% (54 runs sampled)
css => table_cell_traversing_and_direct_desc x 12.55 ops/sec ±1.21% (61 runs sampled)
xpath => table_cell_traversing_and_direct_desc x 13.05 ops/sec ±1.74% (63 runs sampled)
Voici les conclusions issues de ce benchmark:
Vous êtes maintenant bien armés avec des data à jour pour pouvoir choisir la meilleure stratégie de localisation webdriver.
Si vous avez aimé cet article, n’hésitez pas à le partager !