私はSeleniumで(Pythonインターフェースを使用して、そして複数のブラウザーにわたって)複雑なJavaScriptインターフェースをテストしようとしています。私はフォームのボタンをいくつか持っています:
<div>My Button</div>
「マイボタン」(または「マイボタン」や「ボタン」などの大文字と小文字を区別しない、部分一致)に基づいてボタンを検索できるようにしたい
私はこれが驚くほど困難であると感じています。私がこれまでに持っている最高のことは:
driver.find_elements_by_xpath('//div[contains(text(), "' + text + '")]')
ただし、これは大文字と小文字が区別されます。私が試したもう1つのことは、ページ上のすべてのdivを繰り返し処理し、element.textプロパティをチェックすることです。ただし、毎回次のような状況に陥ります。
<div class="outer"><div class="inner">My Button</div></div>
div.outerにはテキストとして "My Button"もあります。これを解決するために、div.outerがdiv.innerの親であるかどうかを調べてみましたが、その方法がわかりませんでした(element.get_element_by_xpath( '..')が要素の親を返しますが、テストはdiv.outerと等しくありません)。また、少なくともChromeウェブドライバを使用した場合、ページ上のすべての要素を繰り返し処理するのは非常に遅いようです。
アイデア?
編集:この質問は少しあいまいになった。ここでより具体的なバージョンを尋ねた(そして答えました): 子要素のテキストを含めずに(Python APIを介して)Selenium WebDriverの要素のテキストを取得する方法?
以下を試してください。
driver.find_elements_by_xpath("//*[contains(text(), 'My Button')]")
次のようにxpathを試すことができます。
'//div[contains(text(), "{0}") and @class="inner"]'.format(text)
Page Object Patternと一緒に使うこともできます。
このコードを試してください:
@FindBy(xpath = "//*[contains(text(), 'Best Choice')]")
WebElement buttonBestChoice;
// * HTMLタグを探します。 Buttonとdivタグに共通のテキストがあり、// *がカテゴリの場合、期待通りに動作しません。特定のものを選択する必要がある場合は、HTML要素タグを宣言することによってそれを取得できます。好きです:
driver.find_element_by_xpath("//div[contains(text(),'Add User')]")
driver.find_element_by_xpath("//button[contains(text(),'Add User')]")
wait.until(ExpectedConditions.visibilityOfElementLocated(By.xpath("//*[contains(text(), 'YourTextHere')]")));
assertNotNull(driver.findElement(By.xpath("//*[contains(text(), 'YourTextHere')]")));
String yourButtonName=driver.findElement(By.xpath("//*[contains(text(), 'YourTextHere')]")).getAttribute("innerText");
assertTrue(yourButtonName.equalsIgnoreCase("YourTextHere"));
興味深いことに、事実上すべての答えはxpathの関数contains()
を中心に展開し、大文字と小文字sensitiveであるという事実を無視します-OPの質問に反します。
大文字と小文字を区別する必要がない場合は、xpath 1.0(最新のブラウザーがサポートするバージョン)で実現できますが、きれいではありません- translate()
を使用して 関数。変換テーブルを使用して、ソース文字を目的の形式に置き換えます。
すべて大文字のテーブルを作成すると、ノードのテキストがlower()形式に効果的に変換され、大文字と小文字を区別しないマッチング(ここでは特権のみ)が許可されます。
[
contains(
translate(text(), 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', 'abcdefghijklmnopqrstuvwxyz'),
'my button'
)
]
# will match a source text like "mY bUTTon"
完全なpython呼び出し:
driver.find_elements_by_xpath("//*[contains(translate(text(), 'ABCDEFGHIJKLMNOPQRSTUVWXYZЙ', 'abcdefghijklmnopqrstuvwxyzй'), 'my button')]")
当然、このアプローチには欠点があります-与えられているように、ラテン語のテキストに対してのみ機能します。 Unicode文字をカバーする場合は、変換テーブルに追加する必要があります。上記のサンプルでこれを実行しました。最後の文字はキリル文字"Й"
です。
そして、ブラウザがxpath 2.0以降をサポートする世界に住んでいた場合(????、しかしすぐには起こりません☹️)、関数 lower-case()
(まだ、完全にロケールを認識しない)、および matches
(正規表現検索の場合、大文字と小文字を区別しない('i'
)フラグ)。
テキストによる要素の大文字と小文字を区別しない検索には、 driver.find_elements_by_xpath および matches regexのマッチング関数を使用します。
driver.find_elements_by_xpath("//*[matches(.,'My Button', 'i')]")
同様の問題:<button>Advanced...</button>
を探す
多分これはあなたにいくつかのアイデアを与えるでしょう(JavaからPythonへ概念を移してください):
wait.until(ExpectedConditions.elementToBeClickable(//
driver.findElements(By.tagName("button")).stream().filter(i -> i.getText().equals("Advanced...")).findFirst().get())).click();