Ich werde die unpopuläre Meinung zu SO-Selen-Tags vertreten, dass XPath auf längere Sicht CSS vorzuziehen ist .
Dieser lange Beitrag besteht aus zwei Abschnitten: Zuerst lege ich einen Beweis für die Rückseite der Serviette vor, dass der Leistungsunterschied zwischen den beiden 0,1 bis 0,3 Millisekunden beträgt (ja, das sind 100 Mikrosekunden ) , und dann teile ich meine Meinung dazu mit XPath ist mächtiger.
Leistungsunterschied
Lassen Sie uns zuerst "den Elefanten im Raum" angehen - dieser xpath ist langsamer als css.
Mit der aktuellen CPU-Leistung (lesen Sie: alles, was x86 seit 2013 produziert) , selbst auf Browserstack- / Saucelabs / aws-VMs, und der Entwicklung der Browser (lesen Sie: alle gängigen in den letzten 5 Jahren) ist dies kaum der Fall. Die Engines des Browsers haben sich entwickelt, die Unterstützung von xpath ist einheitlich, IE ist nicht im Bilde (hoffentlich für die meisten von uns) . Dieser Vergleich in der anderen Antwort wird überall zitiert, ist aber sehr kontextbezogen - wie viele führen die Automatisierung gegen IE8 aus oder kümmern sich darum?
Wenn es einen Unterschied gibt, ist es in einem Bruchteil einer Millisekunde .
Die meisten übergeordneten Frameworks verursachen jedoch ohnehin mindestens 1 ms Overhead gegenüber dem Roh-Selen-Aufruf (Wrapper, Handler, State Storing usw.). Meine persönliche Waffe der Wahl - RobotFramework - fügt mindestens 2 ms hinzu, was ich gerne für das opfere, was sie bietet. Eine Netzwerkrundfahrt von einem AWS us-east-1 zum BrowserStack-Hub dauert normalerweise 11 Millisekunden .
Wenn also bei Remote-Browsern ein Unterschied zwischen xpath und css besteht, wird dieser von allem anderen in Größenordnungen überschattet.
Die Messungen
Es gibt nicht so viele öffentliche Vergleiche (ich habe wirklich nur den zitierten gesehen) , also - hier ist ein grober Einzelfall, Dummy und einfacher.
Es wird ein Element anhand der beiden Strategien X-mal lokalisieren und die durchschnittliche Zeit dafür vergleichen.
Das Ziel - die Zielseite von BrowserStack und die Schaltfläche "Anmelden"; Ein Screenshot des HTML-Codes beim Schreiben dieses Beitrags:
Hier ist der Testcode (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))
Für diejenigen, die nicht mit Python vertraut sind - es öffnet die Seite und findet das Element - zuerst mit dem CSS-Locator, dann mit dem xpath; Die Suchoperation wird 1.000 Mal wiederholt. Die Ausgabe ist die Gesamtzeit in Sekunden für die 1.000 Wiederholungen und die durchschnittliche Zeit für einen Fund in Millisekunden.
Die Locators sind:
- für xpath - "ein div-Element mit genau diesem Klassenwert irgendwo im DOM";
- Das CSS ist ähnlich - "ein div-Element mit dieser Klasse, irgendwo im DOM".
Absichtlich gewählt, um nicht überstimmt zu werden; Außerdem wird der Klassenselektor für das CSS als "der zweitschnellste nach einer ID" angegeben.
Die Umgebung - Chrome v66.0.3359.139, chromedriver v2.38, CPU: ULV Core M-5Y10 läuft normalerweise mit 1,5 GHz (ja, eine "Textverarbeitung", nicht einmal ein normales i7-Biest) .
Hier ist die Ausgabe:
css total time 1000 repeats: 8.84s, per find: 8.84ms
xpath total time for 1000 repeats: 8.52s, per find: 8.52ms
Offensichtlich sind die Zeitpunkte pro Fund ziemlich nahe beieinander. Die Differenz beträgt 0,32 Millisekunden . Springe nicht "der xpath ist schneller" - manchmal ist es, manchmal ist es CSS.
Versuchen wir es mit einem anderen Satz von Locatoren, der etwas komplizierter ist - einem Attribut mit einer Teilzeichenfolge (zumindest für mich ein gängiger Ansatz, der der Klasse eines Elements nachgeht, wenn ein Teil davon eine funktionale Bedeutung hat) :
xpath_locator = '//div[contains(@class, "button-section")]'
css_locator = 'div[class~=button-section]'
Die beiden Locators sind wieder semantisch gleich - "finde ein div-Element, dessen Klassenzeichenfolge in dieser Klasse liegt".
Hier sind die Ergebnisse:
css total time 1000 repeats: 8.60s, per find: 8.60ms
xpath total time for 1000 repeats: 8.75s, per find: 8.75ms
Diff von 0,15 ms .
Als Übung - der gleiche Test wie im verlinkten Blog in den Kommentaren / anderen Antworten - ist die Testseite öffentlich, ebenso wie der Testcode .
Sie machen ein paar Dinge im Code - klicken auf eine Spalte, um danach zu sortieren, dann die Werte abzurufen und zu überprüfen, ob die Sortierung der Benutzeroberfläche korrekt ist.
Ich werde es schneiden - besorgen Sie sich doch nur die Locators - das ist der Wurzeltest, oder?
Der gleiche Code wie oben, mit folgenden Änderungen in:
css_locator = '#table2 tbody .dues'
xpath_locator = "//table[@id='table2']//tr/td[contains(@class,'dues')]"
Und hier ist das Ergebnis:
css total time 1000 repeats: 8.24s, per find: 8.24ms
xpath total time for 1000 repeats: 8.45s, per find: 8.45ms
Diff von 0,2 Millisekunden.
Die "Elemente durch Überqueren finden":
css_locator = '#table1 tbody tr td:nth-of-type(4)'
xpath_locator = "//table[@id='table1']//tr/td[4]"
Das Ergebnis:
css total time 1000 repeats: 9.29s, per find: 9.29ms
xpath total time for 1000 repeats: 8.79s, per find: 8.79ms
Diesmal sind es 0,5 ms (umgekehrt ist xpath hier "schneller" geworden).
Also 5 Jahre später (bessere Browser-Engines) und nur auf die Leistung des Locators fokussiert (keine Aktionen wie Sortieren in der Benutzeroberfläche usw.), dasselbe Testfeld - es gibt praktisch keinen Unterschied zwischen CSS und XPath.
Also, aus xpath und css, welche der beiden für die Leistung wählen? Die Antwort ist einfach - wählen Sie die Suche nach ID .
Kurz gesagt, wenn die ID eines Elements eindeutig ist (wie es den Spezifikationen entsprechen soll), spielt sein Wert eine wichtige Rolle bei der internen Darstellung des DOM durch den Browser und ist daher normalerweise die schnellste.
Es sind jedoch nicht immer eindeutige und konstante (z. B. nicht automatisch generierte) IDs verfügbar. Dies führt uns zu "Warum XPath, wenn es CSS gibt?".
Der XPath-Vorteil
Warum finde ich xpath besser, wenn die Leistung nicht im Bild ist? Einfach - Vielseitigkeit und Kraft.
Xpath ist eine Sprache, die für die Arbeit mit XML-Dokumenten entwickelt wurde. als solches erlaubt es viel leistungsfähigere Konstrukte als CSS.
Zum Beispiel Navigation in alle Richtungen im Baum - finden Sie ein Element, gehen Sie dann zu seinem Großelternteil und suchen Sie nach einem Kind mit bestimmten Eigenschaften.
Es erlaubt eingebettete boolesche Bedingungen - cond1 and not(cond2 or not(cond3 and cond4))
; eingebettete Selektoren - "Finden Sie ein Div mit diesen untergeordneten Elementen mit diesen Attributen und navigieren Sie danach".
XPath ermöglicht die Suche basierend auf dem Wert eines Knotens (seinem Text) - obwohl diese Vorgehensweise verpönt ist, ist es besonders in schlecht strukturierten Dokumenten nützlich (keine bestimmten Attribute, auf die man treten kann, wie dynamische IDs und Klassen) Inhalt) .
Das Einsteigen in CSS ist definitiv einfacher - man kann in wenigen Minuten mit dem Schreiben von Selektoren beginnen; Aber nach ein paar Tagen der Nutzung hat die Leistungsfähigkeit und die Möglichkeiten von xpath CSS schnell überwunden.
Und rein subjektiv - ein komplexes CSS ist viel schwerer zu lesen als ein komplexer xpath-Ausdruck.
Outro;)
Zum Schluss nochmal sehr subjektiv - welches soll man wählen?
IMO, es gibt keine richtige oder falsche Wahl - es handelt sich um unterschiedliche Lösungen für dasselbe Problem, und es sollte ausgewählt werden, was für den Job besser geeignet ist.
Als "Fan" von XPath bin ich nicht schüchtern, in meinen Projekten eine Mischung aus beidem zu verwenden - zum Teufel, manchmal ist es viel schneller, nur ein CSS zu werfen, wenn ich weiß, dass es die Arbeit gut macht.