Подтвердить что ты не робот

Поиск элемента по идентификатору

В чем разница между следующими методами определения местоположения?

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

И с точки зрения производительности, который был бы самым быстрым способом найти элемент по id?

4b9b3361

Ответ 1

Твой вопрос очень трудно ответить, конечно, дать однозначный ответ. На самом деле я испытываю соблазн поставить этот вопрос как "слишком широкий", что подтверждается другими ответами и комментариями.

Возьмите, например, только ваш element(by.id("id"));. Просматривая источник Selenium, большинство драйверов просто берут любой идентификатор, который вы даете, и передаете его на проводной протокол:

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

Как вы знаете, каждый поставщик браузера реализует собственный протокол проводов в отдельном двоичном формате. Не стесняйтесь идти дальше в код, копать более глубокое отверстие для себя.

Для других браузеров, которые не поддерживают проводной протокол, например HtmlUnit, у вас есть что-то вроде:

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

а затем они анализируют доступную DOM.

Что касается вашего вопроса о производительности, все, что вам дает, будет 1) просто чувство, или 2) чистая BS! Которые вы уже можете видеть из других ответов и комментариев, которые вы получаете.

Чтобы получить реальный ответ (поддерживается фактическими данными), есть слишком много переменных:

  • Протокол проводов, реализованный различными поставщиками браузеров, а также различные оптимизации в разных версиях.
  • DOM, реализованные различными поставщиками браузеров, а также различные оптимизации в разных версиях.
  • JavaScript-движки, реализованные различными поставщиками браузеров, а также различные оптимизации в разных версиях.

Кроме того, любые результаты, которые вы получите для своего веб-приложения/веб-страницы, больше всего не будут применяться к другому веб-сайту/веб-странице из-за различий в структуре, используемой для сборки этого сайта.

Нижняя строка: если вас беспокоит тестирование производительности, то Selenium является неправильным ответом. Selenium - это функциональная тестовая библиотека, оптимизированная для предоставления наилучшего представления конечного пользователя. Производительность - отдаленная запоздалая мысль.

Если ваша цель - ускорить выполнение тестов, ваше время будет лучше потрачено на вашу тестовую структуру:

  • Как часто вы открываете/закрываете браузер. Это часто является самой продолжительной активностью в тесте.
  • Как часто вы обновляете кеш-память элемента, как часто вам это нужно? Подумайте о переносе своих элементов на страницу Factory, которая ленивает все элементы для вас.
  • И, конечно же, самый большой фактор ускорения: параллельные тесты на нескольких компьютерах.

Но я думаю, что это выходит из темы (некоторые могут предложить "ranty" ) из вашего начального вопроса.

Ответ 2

Я просто думаю о перспективах производительности и напишу следующий script, чтобы проверить логотип google. Хотя результат сбивает с толку, мы можем сделать статистический результат статистически.

querySelector и getElementById всегда имеют лучший результат, если количество испытаний не превышает 10K. Если мы сравним эти два метода: лучше getElementById (29 из 21).

Если мы сравним их, ID, CSS и XPATH, CSS лучше (29 из 18 и 4), второй - ID и последний XPATH.

Результат моего теста: getElementById, querySelector, CSS, ID, XPATH

См. таблицу, результат и script:

Таблица показывает результат в резюме для 50 попыток:

                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

Результат с разницей времени:

>>> 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)]

код:

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))

Ответ 3

Идентификация различий будет довольно сложной. Вот несколько вещей, которые я нашел -

executeScript() планирует команду выполнить JavaScript как строку в контексте выбранного кадра или окна. Хотя это быстро, читаемость кода низкая.

element() функция, в свою очередь, разрешает findElement() функцию, которая планирует команду для поиска элемента в DOM. Улучшенная читаемость.

Из перспективы производительности по мне, вот рейтинг в порядке возрастания, начиная с самого быстрого, и все они были близки друг к другу с разницей в несколько миллисекунд -

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']"));

Причина того, что javascript executeScript() будет настолько быстрым, состоит в том, что команда, выполненная непосредственно в DOM, без конверсий. Эта ссылка оправдывает их ранжирование между собой.

Оставшиеся зависимые от протокатора локаторы element() медленны, так как транспортиру необходимо преобразовать команды для получения веб-элементов с помощью функции findElement(). Получение элемента id выполняется быстрее, чем использование css и xpath (это также зависит от того, как используются локаторы и часто могут меняться в зависимости от использования).

ПРИМЕЧАНИЕ.. Приведенный выше анализ производительности был средним из многих тестов, которые я запускал локально на своей машине, но он может отличаться в зависимости от системных задач, которые внутренне влияют на запуск тестовых скриптов.

Надеюсь, что это поможет.

Ответ 4


TL; DR; производительность от быстрого до медленного.

  • 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');");

Я попробую. Я попытаюсь объяснить это до точки Protractor и WebdriverJS. Поскольку я не пишу Selenium или драйверы браузера (например, Chromedriver, Firefoxdriver... и т.д.), То есть связь между браузерами и Selenium. Для этого я буду использовать стандартные знания обозревателя для этого момента. Поэтому ответ, он не будет на 100% точным, но в основном.

Я отделяю 5 методов в 2 группах:

1. Общие сообщения

Для первых 3 методов:

элемент (by.id( "ID" ));

элемент (by.css( "# Идентификатор" ));

элемент (by.xpath( "//* [@ID = 'ID']" ));

Все это результат одного HTTP-запроса на сервер Selenium. Который:   '/session/:sessionId/element/:id/element'

С двумя параметрами:

  • using: тип :id. Пример: 'css select', 'id', 'xpath', 'link text'... и т.д.
  • value: значение :id. Пример 'element-id', '.element-css > .child', //*[@id='id']

В этот момент Selenium ответит на запрос соответственно тому, что запрашивается с помощью любого из Chromedriver, Firefoxdriver... и т.д....

В разделе Webdriver find-element-strategy.js. Похоже, что методы сопоставляются с тем, что браузер предоставляет свойства javascript document. Мы получили tag, id, css selector, xpath... и т.д., Которые сопоставляются с document.elementByTagName, document.elementByID, document.querySelecotr, document.evaluate...

Логически в точке зрения кодера я скажу, что ресурс должен использоваться повторно, независимо от того, как эти драйверы были записаны. Например, запрос квеста для id, скорее всего, что-то вроде getElementById должно быть запущено на стороне браузера через драйвер связи.

= > АННОТАЦИЯ Итак, в конце мы имеем:

  • css selector эквивалент querySelector
  • id эквивалент getElementById
  • xpath эквивалент evaluate

2. Инжекционная связь

Для двух последних методов:

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

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

Все это результат одного HTTP-запроса на сервер Selenium. Который:   '/session/:sessionId/execute'

С двумя параметрами:

  • script: текст javascript ('string') или function
  • args: аргументы array

До этого момента речь шла о том, как JS был введен в браузер, так как никто из нас не может быть уверен в поведении (либо используя devtools, либо введя <script> в HTML). Предположим, что он будет одинаковым для всех браузеров.

= > АННОТАЦИЯ Итак, в конце мы проанализируем:

  • querySelector
  • getElementById

Основное сравнение

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

  • element() Оригинал сделан для поиска элементов. Он использует весь профиль метода браузером и его коммуникационный драйвер. Это приведет к увеличению производительности
  • browser.executeScript() был оригинальным не, созданным для поиска элемента. Но для выполнения script, используя его, мы, конечно же, получаем одинаковый результат, но преодолеваем более усложняющий способ достижения той же цели. Поэтому это приведет к более сложному вычислению, чем к элементу finder. И в итоге результат стал более медленным.

= > АННОТАЦИЯ быстро замедляется

  • element()
  • browser.executeScript()

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

Снова каждый браузер будет немного отличаться. Но об этом уже есть какое-то исследование. Я просто использую то, что сообщество было найдено.

css selector известно, что быстрее, чем xpath (источник)

document.querySelector() > FASTER > document.evaluate()

(ПРИМЕЧАНИЕ: xpath не поддерживается IE, поэтому selenium использует свой собственный механизм xpath всякий раз, когда вы используете xpath для IE с транспортиром)

В jsperf.com мы получили this, чтобы сказать

document.getElementById() > FASTER > document.querySelector()

= > РЕЗЮМЕ быстро замедляется

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

3. Суммируйте производительность метода от быстрого до медленного

  • 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');");

Ответ 5

Это был бы широкий ответ, если кто-то попытается ответить на него, поэтому я постараюсь сделать все как можно проще.

Это просто разные способы поиска элементов с использованием селена. Причина, по которой у нас так много альтернатив для выбора элементов, не всегда будет иметь идентификатор или класс, помеченные элементу. Для элементов, которые не имеют идентификатора или класса или имени, единственным вариантом, оставленным с нами, является XPATH.

XPATH может использоваться для уникальной идентификации любого элемента в XML и поскольку HTML (HTML 5, если быть точным, если он написан в соответствии со стандартами) является экземпляром XML, мы можем использовать XPATH для однозначного определения каждого элемента в файле.

Итак, почему бы не использовать XPATH все время? Почему так много альтернатив? Простой, XPATH трудно писать. Например, если нам нужно получить XPATH 'td', который принадлежит таблице, вложенной в 2 другие таблицы. XPATH будет довольно длинным, и большую часть времени мы склонны ошибаться.

Поиск XPATH в firefox довольно прямолинейно, просто установите firepath или firebug и щелкните правой кнопкой мыши на элементе и выберите COPY XPATH.

Подробные инструкции по индикаторам в селене: здесь (представлен в java, но поможет в целом)