【Selenium × Python】excepted_conditionsの条件を整理した

Seleniumでテスト自動化を行う際、待機処理や検証で拡張モジュールのexcepted_conditionsをよく用います。
ただ、どんな条件があるかは把握していなかったので、今回[Github](https://github.com/SeleniumHQ/selenium/blob/trunk/py/selenium/webdriver/support/expected_conditions.py)のページを参考に整理しました。

### 注意事項

- この情報は2022年8月時点のものです。
- また、以下の内容には誤りが含まれる可能性があります。
  - 正しくは、[Githubページ](https://github.com/SeleniumHQ/selenium/blob/trunk/py/selenium/webdriver/support/expected_conditions.py)を参照してください。

## excepted_conditionsの一覧

|No.|条件|返り値|
|:--:|:--|:--:|
||タイトルに着目した条件||
|1|[title_is](#1-title_istitle-str---bool)|bool|
|2|[title_contains](#2-title_containstitle-str---bool)|bool|
||URLに着目した条件||
|3|[url_contains](#3-url_containsurl-str---bool)|bool|
|4|[url_matches](#4-url_matchespattern-str---bool)|bool|
|5|[url_to_be](#5-url_to_beurl-str---bool)|bool|
|6|[url_change](#6-url_changeurl-str---bool)|bool|
||画面要素に着目した条件||
|7|[text_to_be_present_in_element](#7-text_to_be_present_in_elementlocator-str-text_-str---bool)|bool|
|8|[text_to_be_present_in_element_value](#8-text_to_be_present_in_element_valuelocator-str-text_-str---bool)|bool|
|9|[text_to_be_present_in_element_attribute](#9-text_to_be_present_in_element_attributelocator-str-attribute_-str-text_-str---bool)|bool|
|10|[invisibility_of_element_located](#10-invisibility_of_element_locatedlocator-str---bool)|bool|
|11|[invisibility_of_element](#11-invisibility_of_elementelement-str---bool)|bool|
|12|[staleness_of](#12-staleness_ofelement-str---bool)|bool|
|13|[element_to_be_selected](#13-element_to_be_selectedelement-str---bool)|bool|
|14|[element_located_to_be_selected](#14-element_located_to_be_selectedlocator-str---bool)|bool|
|15|[element_selection_state_to_be](#15-element_selection_state_to_beelement-stris_selected-bool---bool)|bool|
|16|[element_located_selection_state_to_be_selected](#16-element_located_selection_state_to_belocaotr-stris_selected-bool---bool)|bool|
|17|[element_attribute_to_include](#17-element_attribute_to_includelocator-strattribute_-str---bool)|bool|
|18|[visibility_of_element_located](#18-visibility_of_element_locatedlocater-str---str)|Webelement|
|19|[visibility_of](#19-visibility_of_element-str---str)|Webelement|
|20|[element_to_be_clickable](#20-element_to_be_clickablemark-str---str)|Webelement|
|21|[presence_of_element_located](#21-presence_of_element_locatedlocater-str---str)|Webelement|
|22|[presence_of_all_elements_located](#22-presence_of_all_elements_locatedlocater-str---list)|list|
|23|[visibility_of_all_elements_located](#23-visibility_of_all_elements_locatedlocater-str---list)|list|
|24|[visibility_of_any_elements_located](#24-visibility_of_any_elements_locatedlocater-str---list)|list|
||frameに着目した条件||
|25|[frame_to_be_available_and_switch_to_it](#25-frame_to_be_available_and_switch_to_itlocator-str---webdriver)|webdriver|
||ウィンドウに着目した条件||
|26|[number_of_windows_to_be](#26-number_of_windows_to_benum_windows-int---bool)|bool|
|27|[new_window_is_opened](#27-new_window_is_openedcurrent_handles-int---bool)|bool|
||ポップアップに着目した条件||
|28|[alert_is_present](#28-alert_is_present)|Alert|
||複合条件||
|29|[any_of](#29-any_ofexpend_conditions---list)|list|
|30|[all_of](#30-all_ofexpend_conditions---list)|list|
|31|[none_of](#31-none_ofexpend_conditions---bool)|bool|

## excepted_conditionsの詳細

### タイトルに着目した条件

#### 1. title_is(title: str): -> bool

- 現在のページのタイトル名がtitleと一致するか（完全一致）
  - 一致すればtrue、そうでなければfalseを返す

#### 2. title_contains(title: str): -> bool

- 現在のページのタイトル名にtitleが含まれているか（部分一致）
  - 含まれている場合はtrueを、そうでなければfalseを返す

<hr>

### URLに着目した条件

#### 3. url_contains(url: str): -> bool

- 現在のページのURLにurlが含まれているか（部分一致）
- urlが含まれる場合はtrueを、含まれない場合はfalseを返す

#### 4. url_matches(pattern: str): -> bool

- 現在のページURLがpatternと一致するか（パターンマッチング[^1]）
  - マッチした場合はture、そうでない場合はfalseを返す

[^1]: 正規表現などを用いて、データを検索する方法

#### 5. url_to_be(url: str): -> bool

- 現在のページのURLがurlと同じであるか（完全一致）
  - 一致する場合はTrueを、一致しない場合はFalseを返す

#### 6. url_change(url: str): -> bool

- 現在のページURLがurlと一致していないか
  - urlと異なる場合はtrueを、そうでない場合はfalseを返す

<hr>

### 画面要素に着目した条件

#### 7. text_to_be_present_in_element(locator: str, text_: str): -> bool

- locator[^2]で指定された要素のtext値にtext_が含まれているかどうか
  - 含まれている場合はtrue、含まれていない場合はfalseを返す

[^2]: 画面上のどの要素を操作するかを指定するための情報

#### 8. text_to_be_present_in_element_value(locator: str, text_: str): -> bool

- locatorで指定された要素のvalue値にtext_が含まれているかどうか
  - 含まれている場合はtrueを、そうでない場合はfalseを返す

#### 9. text_to_be_present_in_element_attribute(locator: str, attribute_: str, text_: str): -> bool

- locatorとattribure[^3]で指定された要素の属性値に、text_がふくまれるかどうか
  - 含まれる場合はtrueを、そうでない場合はfalseを返す

[^3]: web要素の特性のこと。（name属性、id属性、class、リンクを示す<a>等が当てはまる）

#### 10. invisibility_of_element_located(locator: str): -> bool

- locatorで指定した要素が不可視であるか、あるいはDOM[^4]上に存在しないかどうか
  - 不可視もしくは存在しない場合はtrueを、そうでない場合はfalseを返す

[^4]: Document Object Modelの略で、HTMLやXML文書を扱うための手法（API）です。

#### 11. invisibility_of_element(element: str): -> bool

- webelement or locatorで指定した要素が不可視であるか、あるいはDOM上に存在しないかどうか
  - 不可視もしくは存在しない場合はtrueを、そうでない場合はfalseを返す

#### 12. staleness_of(element: str): -> bool

- elementで指定した要素がDOMにアタッチされなくなるまで待つ。
  - 指定した要素がDOMにアタッチされたままの場合はfalseを、そうでなければtrueを返す

#### 13. element_to_be_selected(element: str): -> bool

- elementで指定した要素が選択されているかどうか
  - 選択されている場合はtrueを、未選択の場合はfalseを返す

#### 14. element_located_to_be_selected(locator: str): -> bool

- locatorで指定した要素が選択されているかどうか
  - 選択されている場合はtrueを、未選択の場合はfalseを返す

#### 15. element_selection_state_to_be(element: str,is_selected: bool): -> bool

- elementで指定した要素の選択状況がis_selectedかどうか

```example.py

# hogeという要素が選択されていれば、「選択されている」と出力する

from selenium.webdriver.support import expected_conditions as EC

if EC.element_selection_state_to_be("hoge",tool) == true:
    print("hogeは選択されています")
else:
    print("hogeは選択されていません")

```

#### 16. element_located_selection_state_to_be(locaotr: str,is_selected: bool): -> bool

- locatorで指定した要素の選択状況がis_selsctedかどうか
  - 上記の例と同じで、指定方法がelementからlocatorに変更

#### 17. element_attribute_to_include(locator: str,attribute_: str): -> bool

- locatorで指定された要素の属性にattribute_が含まれるかどうか
  - 含まれている場合はtrueを、そうでなければfalseを返す

#### 18. visibility_of_element_located(locater: str): -> str

- ある要素がページの DOM 上に存在し、可視であるかどうか（locatorの要素が見えているかどうか）
  - DOM上に存在し、見えている場合、WebElement[^5]を返す

[^5]: DOM内の要素オブジェクトのこと（ボタン、テキストボックス等）

#### 19. visibility_of(element: str): -> str

- ある要素がページのDOM上に存在し、かつ要素が見えているかどうか
  - 上記のelementを指定するバージョンです。
  - DOM上に存在し、見えている場合、Webelementを返す

#### 20. element_to_be_clickable(mark: str): -> str

- webelement or locatorで指定された要素が表示され、クリックが有効かどうか
  - 要素が表示され、クリックが有効な場合はwebelementを、そうでない場合はfalseを返す

#### 21. presence_of_element_located(locater: str): -> str

- locaterの可視にかかわらず、locaterの要素がDOM上に存在するかどうか
  - 存在する場合、WebElementを返す。

#### 22. presence_of_all_elements_located(locater: str): -> list

- すべての要素がページのDOM上に存在するかどうか
  - すべて存在した場合、Webelementのリストを返す

#### 23. visibility_of_all_elements_located(locater: str): -> list

- すべての要素がページのDOM上に存在し、可視であるかどうか
  - DOM上に存在し、かつ見えている場合はWebelementのリストを返す

#### 24. visibility_of_any_elements_located(locater: str): -> list

- Webページ上に少なくとも1つの要素が見えているかどうか
  - 見えている場合、Webelementのリストを返す

#### 25. frame_to_be_available_and_switch_to_it(locator: str): -> webdriver

- locatorで指定したフレームがあるかどうか
  - 使用可能な場合、操作対象をlocatorで指定したフレームワークに切り替える
  - 使用不可の場合、falseを返す

<hr>

### ウィンドウに着目した条件

#### 26. number_of_windows_to_be(num_windows: int): -> bool

- ウィンドウの数がnum_windowの値かどうか
  - num_windowsと同じであればtrueを、ことなればfalseを返す

#### 27. new_window_is_opened(current_handles: int): -> bool

- ウィンドウの数がcurrent_handlesの値よりも大きいかどうか
  - ウィンドウの数がcuurent_handlesよりも多い場合はtrueを、そうでない場合はfalseを返す

<hr>

### ポップアップに着目した条件

#### 28. alert_is_present()

- ポップアップが表示されているかどうか
  - ポップアップが表示されている場合は、操作対象をポップアップに移す
  - 表示されていない場合はfalseを返す

<hr>

### 複合条件

#### 29. any_of(*expend_conditions): -> list

- 複数のexpend_conditionsのいずれかがtureかどうか
  - trueの場合、結果取得の値を返す
    - bool、webelement、driver等
  - そうでなければ、falseを返す

#### 30. all_of(*expend_conditions): -> list

- 複数のexpend_conditionsすべてがtrueかどうか
  - すべてtrueの場合は、各expend_conditionの戻り値をふくむリストを返す
    - [true,webelement]
  - そうでなければ、falseを返す

#### 31. none_of(*expend_conditions): -> bool

- 複数のexpend_conditionsすべてがfalseかどうか
  - すべてfalseの場合はtrueを、そうでなければfalseを返す

## excepted_conditionsの活用方法

上記で紹介したexcepted_conditionsの活用方法としては、主に2つです。

### 待機処理（WebDriverWaitと併用して活用）

- 定期時間の待機処理では、ネットワークの状態やPCのスペックによって待機時間が変わっていたものの、excepted_conditionsを活用することで、実行効率があがります。
- 私は[18. visibility_of_element_located](#18-visibility_of_element_locatedlocater-str---str)と[20. element_to_be_clickable](#20-element_to_be_clickablemark-str---str)をよく使用しています。

```.py
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.common.by import By

# hogehogeボタン(id値＝"hogehoge")が有効になるまで待機する（locatorで指定）
# 最大待機時間は10秒ですが、それよりも前にexcepted_conditionsの条件を満たせば、次の処理にすすめる
# 最大待機時間になっても、hogehogeボタンが有効にならない場合は、遷移できていないとしてエラーを投げる
try:
    WebDriverWait(self.driver, 10).until(
        EC.element_to_be_clickable(By.ID,"hogehoge")
        )
except:
    raise Exception("hogehoge画面に遷移できていません。")
```

### 検証処理

- 待機処理と似ていますが、画面遷移先が正しいかどうか検証する際に使っています。
  - [3. url_contains](#3-url_containsurl-str---bool)をよく使っています。

```画面遷移検証.py

from selenium.webdriver.support import expected_conditions as EC

# 現在のページURLにurlが含まれていない場合、エラーを投げる
if EC.url_contains(url :str)==false:
    raise hogehoge画面に遷移できていません

self.driver.find.element~

```

## さいごに

- 今回はseleniumでよく使われるexcepted_conditionsについて整理してみました。
- 整理してみて、「こんなモジュールもあるんだ」と気づけたので、もっとexcepted_conditionsを使いこなしたいと思います。

## 参考資料

- excepted_conditionsのgithubページ

https://github.com/SeleniumHQ/selenium/blob/trunk/py/selenium/webdriver/support/expected_conditions.py

- Selenium実践入門

https://www.amazon.co.jp/Selenium%E5%AE%9F%E8%B7%B5%E5%85%A5%E9%96%80-%E8%87%AA%E5%8B%95%E5%8C%96%E3%81%AB%E3%82%88%E3%82%8B%E7%B6%99%E7%B6%9A%E7%9A%84%E3%81%AA%E3%83%96%E3%83%A9%E3%82%A6%E3%82%B6%E3%83%86%E3%82%B9%E3%83%88-WEB-PRESS-plus/dp/4774178942