web-dev-qa-db-ja.com

IDによる要素の特定

次のロケーションテクニックの違いは何ですか?

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

そして、パフォーマンスの観点から、IDで要素を見つける最も速い方法はどれですか?

24
alecxe

あなたの質問に答えるのは非常に難しく、確かに一つの決定的な答えを出すことは確かです。実際、私はこの質問に「広すぎる」というフラグを立てようとしていますが、これは他の回答やコメントによって裏付けられています。

例えば、あなたのelement(by.id("id"));だけを見てください。 Seleniumのソースを見ると、mostドライバーは、与えられたIDを取得して、ワイヤープロトコルに渡します。

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)feeling、または2)純粋なBSです!あなたがすでに得ている他の回答とコメントからそれを見ることができます。

realの回答(実際のデータでサポートされている)を取得するには、考慮すべき変数が多すぎます。

  • さまざまなブラウザベンダーによって実装されているワイヤプロトコル、およびさまざまなバージョンのさまざまな最適化。
  • さまざまなブラウザーベンダーによって実装されたDOMエンジンと、さまざまなバージョンのさまざまな最適化。
  • さまざまなブラウザベンダーによって実装されたJavaScriptエンジン、およびさまざまなバージョンのさまざまな最適化。

また、Webアプリ/ Webページで得られる結果は、そのサイトを構築するために使用されるフレームワークの違いにより、別のWebアプリ/ Webページに適用しないことが最も好きです。

肝心なのは、パフォーマンステストに不安がある場合、Seleniumは間違った答えです。 Seleniumは、最高のエンドユーザー表現を提供するために最適化された機能テストライブラリです。性能は、後から思いついたものです。

テストの実行を高速化することが目標の場合、テスト構造を見ることで時間を節約できます。

  • ブラウザを開いたり閉じたりする頻度。多くの場合、これはテストで最も時間がかかるアクティビティです。
  • どのくらいの頻度で要素キャッシュを更新し、どのくらいの頻度でneedを必要としますか?要素をPage Factoryモデルに移動することを検討してください。これにより、すべての要素が遅延ロードされます。
  • そしてもちろん、最大のスピードアップ要因は、複数のマシンでテストを並行して実行することです。

しかし、これはあなたの最初の質問から話題になっていると思います(一部は「保証」を示唆するかもしれません)。

9
SiKing

パフォーマンスの観点について考えて、次のスクリプトを作成してGoogleロゴを確認します。結果はわかりにくいですが、統計的に結果を推定できます。

querySelectorおよびgetElementByIdは、試行回数が10Kを超えない限り、常により良い結果をもたらします。これらの2つの方法を比較すると、getElementByIdの方が優れています(21より29)。

そこでこれらを比較すると、[〜#〜] id [〜#〜][〜#〜] css [〜#〜]および[〜 #〜] xpath [〜#〜]、CSSの方が優れています(18と4よりも29)、2番目はIDで、最後の1つはXPATHです。

私のテストの結果:getElementById、querySelector、CSS、ID、XPATH

表、結果、およびスクリプトを参照してください。

表は、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))
6
Mesut GÜNEŞ

違いを特定するのはかなり難しいでしょう。ここに私が見つけたいくつかのものがあります-

executeScript() は、現在選択されているフレームまたはウィンドウのコンテキストで文字列としてJavaScriptを実行するコマンドをスケジュールします。これは高速ですが、コードの可読性は低くなります。

element() functionは、DOM上の要素を見つけるコマンドをスケジュールする findElement() functionに解決されます。読みやすさの改善。

私によると、パフォーマンスの観点から、ここでは、昇順でのランキングを最速のものから始めており、それらはすべて数ミリ秒の差で互いに近かった-

_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()関数を使用してWeb要素を取得するためにコマンドを変換する必要があるため、低速です。 idによる要素の取得は、cssおよびxpathを使用するよりも高速です(これはロケーターの使用方法にも依存し、使用法に応じて変更されることがよくあります)。

注:上記のパフォーマンス分析は、マシンでローカルに実行した多くのテストの平均でしたが、実行に内部的に影響するシステムタスクに基づいて異なる場合がありますテストスクリプト。

それが役に立てば幸い。

4
Girish Sortur

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

これを試してみます。 ProtractorWebdriverJSのポイントまで説明しようとします。私はブラウザとSelenium間の通信であるChromedriverまたはブラウザのドライバ(例えばFirefoxdriverSelenium...など)を書いていないので。このため、この点についてはブラウザーのエンジンに関する標準的な知識を使用します。したがって、答えは、100%正確ではありませんが、ほとんどの場合です。

5つのメソッドを2つのグループに分けます。

1.一般的なコミュニケーション

最初の3つの方法の場合:

element(by.id( "id"));

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

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

これらはすべて、Seleniumサーバーへの単一のHTTP要求の結果です。どちらか:_'/session/:sessionId/element/:id/element'_

2つのパラメーター:

  • using:_:id_のタイプ。例:_'css select'_、_'id'_、 '_xpath'_、_'link text'_...など.
  • value:_:id_の値。例_'element-id'_、_'.element-css > .child'_、_//*[@id='id']_

この時点で、Seleniumは、ChromedriverFirefoxdriver...などのいずれかを介して要求されている内容に応じて要求に応答します。

Webdriver find-element-strategy.js の下で。メソッドは、ブラウザがjavascript documentプロパティによって提供するものにマッピングされているようです。 tagid、_css selector_、xpath...などを取得しました。これらは_document.elementByTagName_、_document.elementByID_、 _document.querySelecotr_、_document.evaluate_...

コーダーの観点から論理的に言うと、これらのドライバーがどのように記述されたかに関係なく、リソースは再利用されるべきです。たとえば、idのクエストリクエストは、おそらくgetElementByIdのようなものが、通信ドライバーを介してブラウザー側でトリガーされるようになります。

=>[〜#〜] summary [〜#〜]したがって、最終的には次のようになります。

  • _css selector_ querySelectorと同等
  • idと同等のgetElementById
  • xpathと同等のevaluate

2.通信の注入

最後の2つの方法の場合:

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

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

これらはすべて、Seleniumサーバーへの単一のHTTP要求の結果です。どちらか:_'/session/:sessionId/execute'_

2つのパラメーター:

  • script:javascriptテキスト(_'string'_)またはfunction
  • args:引数はarrayです

ここまでは、JSがブラウザにどのように挿入されたかについてでした。私たちは誰も動作を確認できません(devtoolsを使用するか、HTMLに_<script>_を挿入します)。すべてのブラウザで同じであると仮定しましょう。

=>[〜#〜] summary [〜#〜]したがって、最終的に分析します:

  • querySelector
  • getElementById

主な比較

1。element()vsbrowser.executeScript()

  • element()要素を見つけるために作成されたオリジナル。ブラウザおよび通信ドライバごとにすべてのメソッドプロファイルを使用しています。これにより、パフォーマンスが向上します
  • browser.executeScript()はオリジナルでしたnotは、素子。しかし、スクリプトを実行するために、それを使用することにより、もちろん同じ結果が得られますが、同じ目標を達成するためにより複雑な方法を経ています。したがって、これは要素ファインダーを使用するよりも複雑な計算になります。その結果、パフォーマンスが低下しました。

=> SUMMARY高速から低速

  • element()
  • browser.executeScript()

2。document.querySelector()vsdocument.getElementById()vsdocument.querySelector()

繰り返しますが、各ブラウザはわずかに違いが生じます。しかし、これについてはすでにいくつかの研究があります。見つかったコミュニティを使用します。

_CSS selector_はxpathよりも高速であることを知っている( source

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

(注:IEではxpathはサポートされていないため、xpath on IE with protractor)を使用している場合は常にSeleniumは独自のxpathエンジンを使用します)

_jsperf.com_ を得ました this そのことをテストします

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

=> SUMARY高速から低速

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

誰かがそれに答えようとするなら、それは幅広い答えになるでしょう、それで私はできる限り簡単にするようにします。

これらは、Seleniumを使用して要素を見つけるためのさまざまな方法です。要素を選択するための選択肢が非常に多いのは、常に要素にタグ付けされたidまたはclassがあるからではありません。 idまたはclassまたはnameを持たない要素については、XPATHのみが残されています。

XPATHはXMLの要素を一意に識別するために使用できます。HTML(標準に従って記述されている場合、正確にはHTML 5)はXMLのインスタンスであるため、XPATHを使用してファイル内のすべての要素を一意に識別できます。

では、XPATHを常に使用しないのはなぜですか?なぜこれほど多くの選択肢があるのですか?シンプルで、XPATHを書くのは難しいです。たとえば、他の2つのテーブル内にネストされたテーブルに属する 'td'のXPATHを取得する必要がある場合。 XPATHはかなり長くなり、ほとんどの場合、間違いを犯しがちです。

FirefoxでXPATHを見つけるのは簡単です。単純にfirepathまたはfirebugをインストールし、要素を右クリックして[COPY XPATH]を選択します。

Seleniumのインジケーターの詳細な説明: here (Javaで表示されますが、一般的に役立ちます)

0
Revanth Kumar