Localización de un elemento por id


¿Cuál es la diferencia entre las siguientes técnicas de localización?

  1. element(by.id("id"));
  2. element(by.css("#id"));
  3. element(by.xpath("//*[@id='id']"));
  4. browser.executeScript("return document.querySelector('#id');");
  5. browser.executeScript("return document.getElementById('id');");

Y, desde la perspectiva del rendimiento , ¿cuál sería la forma más rápida de localizar un elemento por id?

Author: alecxe, 2015-12-30

5 answers

Su pregunta es muy difícil de responder, ciertamente para dar una sola respuesta concluyente. De hecho, estoy tentado de señalar esta pregunta como "demasiado amplia", lo que está respaldado por las otras respuestas y comentarios.

Tome, por ejemplo, solo su element(by.id("id"));. Mirando a través de la fuente de Selenio, la mayoría de los controladores simplemente toman cualquier id que den y lo pasan al protocolo de cable:

public WebElement findElementById(String using) {
  if (getW3CStandardComplianceLevel() == 0) {
    return findElement("id", using);
  } else {
    return findElementByCssSelector("#" + cssEscape(using));
  }
}

Como usted sabe, cada proveedor de navegadores implementa su propio protocolo de cable en un binario separado. Siéntase libre de ir más lejos en el código, para cavar un agujero más profundo para su auto.

Para otros navegadores que no soportan el protocolo wire, por ejemplo HtmlUnit, solo tienes algo como:

public List<WebElement> findElementsById(String id) {
  return findElementsByXPath("//*[@id='" + id + "']");
}

Y luego analizan el DOM disponible.

En cuanto a tu pregunta de rendimiento, cualquier cosa que alguien te dé será 1) solo una sensación, o 2) ¡pura mierda! Que ya se puede ver en las otras respuestas y comentarios que está recibiendo.

Para obtener un real respuesta (apoyada por datos reales), hay demasiadas variables a considerar:

  • Protocolo de cable implementado por diferentes proveedores de navegadores, además de varias optimizaciones en diferentes versiones.
  • Motores DOM implementados por diferentes proveedores de navegadores, además de varias optimizaciones en diferentes versiones.
  • Motores JavaScript implementados por diferentes proveedores de navegadores, además de varias optimizaciones en diferentes versiones.

También, cualquiera que sea el resultado usted consigue para su aplicación web / página web más como no aplicar a una aplicación web diferente / página web, debido a las diferencias en el marco utilizado para construir ese sitio.

La conclusión es: Si le preocupan las pruebas de rendimiento, entonces el Selenio es la respuesta incorrecta. Selenium es una biblioteca de pruebas funcional, optimizada para darle la mejor representación del usuario final. El rendimiento es una idea tardía.

Si su objetivo es hacer que sus pruebas se ejecuten más rápido, su tiempo se gastará mejor mirando su estructura de prueba:

  • Con qué frecuencia abre/cierra el navegador. Esta es a menudo la actividad que consume más tiempo en una prueba.
  • ¿Con qué frecuencia actualiza su caché de elementos, con qué frecuencia necesita? Considere mover sus elementos al modelo Page Factory, que carga perezosamente todos los elementos por usted.
  • Y, por supuesto, el mayor factor de aceleración: ejecutar sus pruebas en paralelo en varias máquinas.

Pero creo que esto es saliendo del tema (algunos podrían sugerir "garantía") de su pregunta inicial.

 9
Author: SiKing,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-01-08 00:28:58

Solo pienso en la perspectiva del rendimiento y escribo el siguiente script para verificar el logotipo de Google. Aunque el resultado es confuso, podemos hacer una estimación del resultado estadísticamente.

QuerySelector y getElementById siempre tienen un mejor resultado, a menos que el número de ensayos sea superior a 10K. Si comparamos estos dos métodos: getElementById es mejor (29 sobre 21).

Si comparamos estas allí, ID, CSS y XPATH, CSS es mejor (29 sobre 18 y 4), el segundo es ID y el último XPATH.

El resultado de mi prueba: getElementById, querySelector, CSS, ID, XPATH

Ver la tabla, el resultado y el script:

La tabla muestra el resultado en resumen para 50 intentos:

                1   2   3   4   5
ID              0   0   18  24  8
CSS             0   0   29  18  3
XPATH           0   0   4   12  34
querySelector   21  29  0   0   0
getElementById  29  21  0   0   0

Resultado con diferencia de tiempo:

>>> for i in range(50):
...  test_time(1)
...
[('getElementById', 0.004777193069458008), ('querySelector', 0.006440162658691406), ('id', 0.015267133712768555), ('css', 0.015399932861328125), ('xpath', 0.015429019927978516)]
[('querySelector', 0.006442070007324219), ('getElementById', 0.00728607177734375), ('id', 0.013181924819946289), ('css', 0.014509916305541992), ('xpath', 0.015583992004394531)]
[('getElementById', 0.0063440799713134766), ('querySelector', 0.006493091583251953), ('css', 0.014523029327392578), ('id', 0.014902830123901367), ('xpath', 0.015790224075317383)]
[('getElementById', 0.007112026214599609), ('querySelector', 0.007357120513916016), ('id', 0.014781951904296875), ('css', 0.015780925750732422), ('xpath', 0.016005992889404297)]
[('getElementById', 0.006434917449951172), ('querySelector', 0.007117033004760742), ('id', 0.01497507095336914), ('css', 0.015005111694335938), ('xpath', 0.015393972396850586)]
[('querySelector', 0.00563812255859375), ('getElementById', 0.006503105163574219), ('css', 0.014302968978881836), ('id', 0.014812946319580078), ('xpath', 0.017061948776245117)]
[('querySelector', 0.0048770904541015625), ('getElementById', 0.006540060043334961), ('css', 0.014795064926147461), ('id', 0.015192985534667969), ('xpath', 0.016000986099243164)]
[('getElementById', 0.006265878677368164), ('querySelector', 0.006501913070678711), ('id', 0.014132022857666016), ('css', 0.01437997817993164), ('xpath', 0.014840841293334961)]
[('getElementById', 0.006368160247802734), ('querySelector', 0.006601095199584961), ('css', 0.01462101936340332), ('id', 0.014872074127197266), ('xpath', 0.016145944595336914)]
[('querySelector', 0.00642704963684082), ('getElementById', 0.006908893585205078), ('css', 0.014439105987548828), ('id', 0.014970064163208008), ('xpath', 0.015510082244873047)]
[('getElementById', 0.006404876708984375), ('querySelector', 0.006679058074951172), ('css', 0.014878988265991211), ('id', 0.01546788215637207), ('xpath', 0.015535116195678711)]
[('querySelector', 0.005848884582519531), ('getElementById', 0.008013010025024414), ('css', 0.014436006546020508), ('xpath', 0.01566910743713379), ('id', 0.015830039978027344)]
[('querySelector', 0.006299018859863281), ('getElementById', 0.006538867950439453), ('css', 0.014534950256347656), ('id', 0.014979124069213867), ('xpath', 0.01618194580078125)]
[('getElementById', 0.006415128707885742), ('querySelector', 0.006479978561401367), ('id', 0.014901876449584961), ('css', 0.014998912811279297), ('xpath', 0.01544499397277832)]
[('getElementById', 0.006515979766845703), ('querySelector', 0.006515979766845703), ('xpath', 0.014292001724243164), ('css', 0.014482975006103516), ('id', 0.015102863311767578)]
[('getElementById', 0.00574803352355957), ('querySelector', 0.006389141082763672), ('css', 0.014650821685791016), ('id', 0.014751911163330078), ('xpath', 0.01532888412475586)]
[('getElementById', 0.0063037872314453125), ('querySelector', 0.006974935531616211), ('id', 0.014775991439819336), ('css', 0.014935970306396484), ('xpath', 0.015460968017578125)]
[('getElementById', 0.0064661502838134766), ('querySelector', 0.0065021514892578125), ('id', 0.014723062515258789), ('css', 0.014946937561035156), ('xpath', 0.015508890151977539)]
[('getElementById', 0.006738901138305664), ('querySelector', 0.008143901824951172), ('css', 0.014575004577636719), ('xpath', 0.015228986740112305), ('id', 0.015702009201049805)]
[('getElementById', 0.006436824798583984), ('querySelector', 0.0064470767974853516), ('css', 0.014545917510986328), ('id', 0.014694929122924805), ('xpath', 0.015357017517089844)]
[('querySelector', 0.006292104721069336), ('getElementById', 0.006451845169067383), ('css', 0.014657020568847656), ('xpath', 0.01574397087097168), ('id', 0.016795873641967773)]
[('getElementById', 0.006443977355957031), ('querySelector', 0.006485939025878906), ('css', 0.013139009475708008), ('id', 0.014308929443359375), ('xpath', 0.015516042709350586)]
[('querySelector', 0.006464958190917969), ('getElementById', 0.006821870803833008), ('id', 0.016110897064208984), ('css', 0.01633286476135254), ('xpath', 0.017225980758666992)]
[('getElementById', 0.005715131759643555), ('querySelector', 0.008069992065429688), ('css', 0.014779090881347656), ('id', 0.01491093635559082), ('xpath', 0.015527963638305664)]
[('getElementById', 0.006309986114501953), ('querySelector', 0.006836891174316406), ('css', 0.01497507095336914), ('id', 0.015040159225463867), ('xpath', 0.02096104621887207)]
[('querySelector', 0.00616908073425293), ('getElementById', 0.007357120513916016), ('css', 0.014974832534790039), ('id', 0.015640974044799805), ('xpath', 0.016278982162475586)]
[('querySelector', 0.005301952362060547), ('getElementById', 0.0063440799713134766), ('id', 0.014526844024658203), ('css', 0.014657974243164062), ('xpath', 0.0162200927734375)]
[('querySelector', 0.005811929702758789), ('getElementById', 0.007221221923828125), ('css', 0.01259613037109375), ('xpath', 0.014851093292236328), ('id', 0.015043020248413086)]
[('getElementById', 0.006195068359375), ('querySelector', 0.007548093795776367), ('css', 0.01441502571105957), ('id', 0.01441812515258789), ('xpath', 0.016713857650756836)]
[('querySelector', 0.0050449371337890625), ('getElementById', 0.006323099136352539), ('id', 0.01497793197631836), ('css', 0.014984130859375), ('xpath', 0.015444040298461914)]
[('getElementById', 0.007039070129394531), ('querySelector', 0.008107900619506836), ('xpath', 0.015566825866699219), ('id', 0.015954017639160156), ('css', 0.01815509796142578)]
[('getElementById', 0.005831003189086914), ('querySelector', 0.007988214492797852), ('id', 0.014652013778686523), ('css', 0.014683008193969727), ('xpath', 0.01581597328186035)]
[('querySelector', 0.006363868713378906), ('getElementById', 0.006494998931884766), ('xpath', 0.01517796516418457), ('id', 0.016071796417236328), ('css', 0.017260074615478516)]
[('getElementById', 0.00633692741394043), ('querySelector', 0.007826089859008789), ('css', 0.014354944229125977), ('id', 0.015484809875488281), ('xpath', 0.017076969146728516)]
[('querySelector', 0.006349802017211914), ('getElementById', 0.006428956985473633), ('css', 0.01385188102722168), ('id', 0.014858007431030273), ('xpath', 0.016836166381835938)]
[('querySelector', 0.006417989730834961), ('getElementById', 0.007012844085693359), ('css', 0.01460719108581543), ('id', 0.014763832092285156), ('xpath', 0.015476226806640625)]
[('getElementById', 0.006266117095947266), ('querySelector', 0.0074520111083984375), ('id', 0.014987945556640625), ('css', 0.01515817642211914), ('xpath', 0.015646934509277344)]
[('getElementById', 0.006376981735229492), ('querySelector', 0.0064089298248291016), ('id', 0.01494598388671875), ('css', 0.015275001525878906), ('xpath', 0.01553201675415039)]
[('getElementById', 0.006357908248901367), ('querySelector', 0.006699085235595703), ('css', 0.014505147933959961), ('xpath', 0.015446186065673828), ('id', 0.019747018814086914)]
[('getElementById', 0.0063610076904296875), ('querySelector', 0.0064640045166015625), ('css', 0.014472007751464844), ('id', 0.014828205108642578), ('xpath', 0.01532888412475586)]
[('getElementById', 0.0063610076904296875), ('querySelector', 0.006580829620361328), ('css', 0.012439966201782227), ('id', 0.014935016632080078), ('xpath', 0.015373945236206055)]
[('querySelector', 0.006309032440185547), ('getElementById', 0.006561994552612305), ('id', 0.014923095703125), ('css', 0.015380859375), ('xpath', 0.01574110984802246)]
[('querySelector', 0.006357908248901367), ('getElementById', 0.006387948989868164), ('css', 0.01481485366821289), ('id', 0.015089988708496094), ('xpath', 0.015390872955322266)]
[('querySelector', 0.004536867141723633), ('getElementById', 0.00640416145324707), ('css', 0.014551877975463867), ('xpath', 0.014974117279052734), ('id', 0.014991998672485352)]
[('getElementById', 0.006387233734130859), ('querySelector', 0.00643610954284668), ('css', 0.014494895935058594), ('id', 0.014873981475830078), ('xpath', 0.015212059020996094)]
[('getElementById', 0.0063588619232177734), ('querySelector', 0.006443977355957031), ('css', 0.013200998306274414), ('id', 0.014631986618041992), ('xpath', 0.015624046325683594)]
[('getElementById', 0.0048558712005615234), ('querySelector', 0.005300045013427734), ('id', 0.014750003814697266), ('css', 0.014846086502075195), ('xpath', 0.015408992767333984)]
[('querySelector', 0.008347034454345703), ('getElementById', 0.008370161056518555), ('id', 0.014650106430053711), ('css', 0.014775991439819336), ('xpath', 0.015323877334594727)]
[('querySelector', 0.006309032440185547), ('getElementById', 0.007323026657104492), ('css', 0.014546871185302734), ('xpath', 0.015864133834838867), ('id', 0.02078390121459961)]
[('querySelector', 0.007790088653564453), ('getElementById', 0.010209083557128906), ('id', 0.015320062637329102), ('xpath', 0.01600193977355957), ('css', 0.01807403564453125)]

Código:

from timeit import default_timer as timer
import time, operator
from selenium import webdriver

def open_browser():
    dr = webdriver.Chrome()
    dr.get('http://www.google.com')
    time.sleep(5)
    return dr,timer()

def quit_browser(el, start, dr, result):
    diff = timer() - float(start)
    result[el] = diff
    dr.quit()

def test_time(tm):
    result = {}

    dr, start = open_browser()
    for i in range(tm):
        dr.find_element_by_id('hplogo')
    quit_browser("id", start, dr, result)

    dr, start = open_browser()
    for i in range(tm):
        dr.find_element_by_css_selector('#hplogo')
    quit_browser("css", start, dr, result)

    dr, start = open_browser()
    for i in range(tm):
        dr.find_element_by_xpath("//*[@id='hplogo']")
    quit_browser("xpath", start, dr, result)

    dr, start = open_browser()
    for i in range(tm):
        dr.execute_script("return document.querySelector('#hplogo');")
    quit_browser("querySelector", start, dr, result)

    dr, start = open_browser()
    for i in range(tm):
        dr.execute_script("return document.getElementById('hplogo');")
    quit_browser("getElementById", start, dr, result)

    print sorted(result.items(), key=operator.itemgetter(1))
 5
Author: Mesut GÜNEŞ,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-01-08 12:04:37

TL;DR; rendimiento en orden de rápido a lento.

  • element(by.id("id"));
  • element(by.css("#id"));
  • element(by.xpath("//*[@id='id']"));
  • browser.executeScript("return document.getElementById('id');");
  • browser.executeScript("return document.querySelector('#id');");

Voy a intentarlo. Trataré de explicarlo hasta el punto de Protractor y WebdriverJS. Como no estoy escribiendo Selenium o los controladores del navegador (Por ejemplo. Chromedriver, Firefoxdriver... sucesivamente...) que es la comunicación entre navegadores y Selenium. Para esto voy a utilizar el conocimiento estándar del motor del navegador para este punto. Por lo tanto, la respuesta, no será 100% exacto pero sobre todo.

Separaré 5 métodos en 2 grupos:

1. Comunicaciones comunes

Para los primeros 3 métodos:

Elemento(by.id ("id"));

Elemento (by.css("#id"));

Elemento (by.xpath ("//*[@id = 'id']"));

Todos estos son el resultado de una sola solicitud HTTP al servidor Selenium. Que es: '/session/:sessionId/element/:id/element'

Con 2 parámetros:

  • using : tipo de :id . Ejemplo: 'css select', 'id', 'xpath', 'link text'... sucesivamente..
  • value : valor de :id. Ejemplo 'element-id', '.element-css > .child', //*[@id='id']

En este punto Selenium responderá a la solicitud en consecuencia a lo que se solicita a través de cualquiera de Chromedriver, Firefoxdriver... sucesivamente...

Bajo Webdriver find-element-strategy.js. Como parece que los métodos están mapeados con lo que proporciona el navegador javascript document propiedades. Tenemos tag, id, css selector, xpath... sucesivamente.. que se empareja con document.elementByTagName, document.elementByID, document.querySelecotr, document.evaluate...

Lógicamente desde el punto de vista de un codificador, diré que el recurso debe reutilizarse independientemente de cómo se escribieron estos controladores. Por ejemplo, quest request para id lo más probable es que algo como getElementById tenga que activarse en el lado del navegador a través del controlador de comunicación.

=> RESUMEN, Así que al final tenemos:

  • css selector equivalente a querySelector
  • id equivalente a getElementById
  • xpath equivalente a evaluate

2. Inyección de comunicaciones

Para 2 últimos métodos:

Navegador.executeScript ("return document.querySelector ('#id');");

Navegador.executeScript ("return document.getElementById ('id');");

Todos estos son el resultado de una sola solicitud HTTP al servidor Selenium. Que es: '/session/:sessionId/execute'

Con 2 parámetros:

  • script: texto javascript ('string') o a function
  • args: argumentos es un array

Hasta este punto, se trata de cómo JS se inyectó en el navegador, ya que ninguno de nosotros puede estar seguro del comportamiento (ya sea usando devtools o inyectando <script> en HTML). Supongamos que será el mismo para todos los navegadores.

=> RESUMEN, Así que al final vamos a analizar :

  • querySelector
  • getElementById

Comparación principal

1. element() vs browser.executeScript():

  • element () Original hecho para localizar elementos. Está utilizando todo el perfil de método por navegador y controlador de comunicación de ti. Esto resultará como un rendimiento más rápido
  • navegador.executeScript () fue original no hecho para usar para localizar un elemento. Pero para ejecutar un script, al usarlo, por supuesto, estamos obteniendo el mismo resultado, pero pasando por una forma más complicada para lograr el mismo objetivo. Por lo tanto, esto resultará en un cálculo más complicado que usar element finder. Y terminó resultando un rendimiento más lento.

=> RESUMEN rápido a lento

  • element()
  • browser.executeScript()

2. document.querySelector() vs document.getElementById() vs document.querySelector():

De nuevo cada navegador resultará en una ligera diferencia. Pero ya hay algunas investigaciones sobre esto. Voy a usar lo que la comunidad ha sido encontrar.

CSS selector ser saber que más rápido que xpath (source )

document.querySelector() > MÁS RÁPIDO > document.evaluate()

(NOTA: IE no admite xpath, por lo que selenium usa su propio motor xpath cuando usa xpath en IE con transportador)

El jsperf.com tenemos esto prueba ese dicho

document.getElementById() > MÁS RÁPIDO > document.querySelector()

=> SUMARIO rápido a lento

  • document.getElementById()
  • document.querySelector()
  • document.evaluate()

3. Resumen del rendimiento del método de rápido a lento

  • element(by.id("id"));
  • element(by.css("#id"));
  • element(by.xpath("//*[@id='id']"));
  • browser.executeScript("return document.getElementById('id');");
  • browser.executeScript("return document.querySelector('#id');");
 4
Author: Linh Pham,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-23 12:26:32

Identificar diferencias sería bastante difícil. Aquí hay algunas cosas que encontré -

executeScript() programa un comando para ejecutar JavaScript como una cadena en el contexto del marco o ventana seleccionado actualmente. Aunque esto es rápido, la legibilidad del código es baja.

element() función a su vez resuelve a findElement() función que programa un comando para encontrar el elemento en el DOM. Legibilidad mejorada.

Desde la perspectiva del desempeño según mí, aquí están los rankings en orden ascendente comenzando con el más rápido y todos ellos estaban cerca uno del otro con diferencias en pocos milisegundos -

1 - browser.executeScript("return document.getElementById('id');");
2 - browser.executeScript("return document.querySelector('#id');");
3 - element(by.id("id"));
4 - element(by.css("#id"));
5 - element(by.xpath("//*[@id='id']"));

La razón de que javascript executeScript() sea tan rápido es porque el comando se ejecuta en DOM directamente sin conversiones. Este enlace justifica sus clasificaciones entre sí.

Los localizadores específicos del transportador restantes element() son lentos, ya que el transportador necesita convertir los comandos para obtener los elementos web usando la función findElement(). Obtener elemento por id es más rápido que usar css y xpath (Esto también depende de cómo se usen los localizadores y, a menudo, puede cambiar según el uso).

NOTA: El análisis de rendimiento anterior fue el promedio de muchas pruebas que ejecuté localmente en mi máquina, pero puede diferir en función de las tareas del sistema que afectan internamente la ejecución de los scripts de prueba.

Espero que ayude.

 3
Author: Girish Sortur,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-01-07 14:24:40

Sería una respuesta amplia si alguien intenta responderla, así que trataré de hacerlo lo más simple posible.

Estas son solo diferentes formas de encontrar elementos usando selenio. La razón por la que tenemos tantas alternativas para seleccionar elementos es, no siempre tendremos id o clase etiquetada a un elemento. Para los elementos que no tienen id, clase o nombre, la única opción que nos queda es XPATH.

XPATH se puede utilizar para identificar de forma única cualquier elemento en un XML y desde HTML (HTML 5 para ser precisos, si se escribe de acuerdo con los estándares) es una instancia de XML que podemos utilizar XPATH para identificar de forma única cada elemento en el archivo.

OK Entonces, ¿por qué no usar XPATH todo el tiempo? Por qué tantas alternativas? Simple, XPATH es difícil de escribir. Por ejemplo, si necesitamos obtener el XPATH de un 'td' que pertenece a una tabla anidada dentro de otras 2 tablas. XPATH será bastante largo y la mayoría de las veces tendemos a cometer un error.

Encontrar XPATH en firefox es bastante sencillo adelante, simplemente instale firepath o firebug y haga clic derecho en el elemento y seleccione COPIAR XPATH.

Instrucciones detalladas sobre los indicadores en selenio: aquí (presentado en java pero ayudará en general)

 0
Author: Revanth Kumar,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-01-12 15:59:19