PythonのSeleniumラッパーSeleneの使い方
概要
JavaのSeleniumWebDriverラッパーとしてはSelenideが有名ですが、PythonではSeleneがメジャーなようです。
公式のドキュメント等見てもイマイチわからないところが多かったので、自分で調べてみたついでにわかったことを残しておきます。
※色々調べてみた感想としては、Seleneの中身読むのが一番わかりやすかったです。
そもそもSelenとは
- Effective web test automation toolである
- 簡潔なAPI
- 要素等の検索を待つ
- アサートを待つ
- 動的な要素にも対応
- UIテストのロジックを自動化するもの
準備
手元の環境
- Windows10Pro
- Python 3.7.2
- Selenium WebDriver 3.141.0
- pytest 5.0.0
- GoogleChrome 77
- FireFox 70
環境構築
SeleniumWebDriverとPythonで自動テストを書ける状態に加えて、Seleneのインストールが必要です。
インストール手順などは公式に書いてあります。
yashaka/selene: Concise UI tests in Python + Ajax support + PageObjects
が、バージョンごとに複数手順があるようなので、今回は
latest published pre-release version (currently this is recommended option unless selene 1.0 will be released):
と書いてある最新のプレリリース版を使おうと思います。
$ pip install selene --pre
使い方
画面の要素を取得する
browser.element('#new-todo')
のように書くことができますが、基本はより短いs
を使います。
find_element_by_id("hoge")
と書くかわりに、
s('#hoge')
s(by.id('hoge'))
のいずれかの書き方ができます。
一つめのほうは、sの引数にそのままCSSセレクタを書くパターン。もうひとつのほうは、byを使ってidなりxpathなりを使う、生のWebDriverに近いパターン。
いずれにせよ、行は減らないものの文字数はだいぶ減っています。ただ、読んで理解しやすいかというと怪しいかもしれませんね。
sは"search element"のsだそうです。
find_elements_by_hoge
を行いたいときには、ss
を使います。
ss('#todo-list>li')
こちらは、browser.all('#todo-list>li')
とも書けますが、やはり短いss
のほうを公式も勧めています。
スクリーンショット取得
生のWebDriverだとsave_screenshot()
メソッドを使うところ、Seleneの場合はtake_screenshot()
になるようです。
take_screenshot()
はパスとファイル名の二つの引数をとり、どちらも書かなくても動くようにはなっています。
第一引数で指定するパスはスクリーンショットの保存先のパス、第二引数で指定するファイル名はスクリーンショットのファイル名です。
たとえば、
browser.take_screenshot(".\\capture")
とだけ書いた場合。この場合は、スクリプトと同階層にcaptureというフォルダができ、そこにスクリーンショットがどんどん追加されていきます。
このときのファイル名は過去のものと重複しないようにSeleneが付けてくれます。screen_1571995717156.png
のような名前になります。
引数に何も指定しないと、デフォルトのレポート保存先に"screenshots"というフォルダを作って保存されます。
私の手元の例は↓です。
C:\Users\yoshiki.itou\.selene\screenshots\1572231343309\screen_1572231343310.png
毎回保存先を指定するのが面倒な場合は、引数指定なしの場合の保存先を設定変更することができます。
config.reports_folder = ".//screenshot/"
と書くと、実行したテストスクリプトと同じ階層にscreenshotsというフォルダを作り、その中にスクリーンショットを保存していきます。
タイムアウトの設定
例えば
python
s("#new-todo").should_be(enabled)
とだけ書いた場合、デフォルトでタイムアウトは4秒。
s("#new-todo").should_be(enabled, timeout=10)
と書けば、この場合のタイムアウトが10秒になります。
もしくは
config.timeout = 10
と書いておけば、以降のタイムアウトが10秒になります。
実行するブラウザの指定
SeleneはAutomatic driver managementというのをやってくれるので、自分でダウンロードしてきたhogedriver.exeのパスを指定or環境変数PATHを通して・・・という作業をしなくて済むようになっています。
このへんはSergeyPirogov/webdriver_managerを利用しているようです。
デフォルトではChromeが起動するようになっているようですが、明示的に指定する場合は以下のように書きます。
from selene import config
from selene.browsers import BrowserName
config.browser_name = BrowserName.CHROME
FireFoxで動かしたい場合、CHROMEのところを単純に
Python
config.browser_name = BrowserName.FIREFOX
にすればうまくいくだろうと思ったのですが、私の環境ではエラーで動作せず。
中身見てみたところ、どうも
config.browser_name = BrowserName.MARIONETTE
だと動作するようでした。
※ここについては、みんなそうだという自信はないので、FIREFOXでダメなときはお試しください。
selene/browsers.py at master · yashaka/seleneあたりを見てみても、FIREFOX自体は設定できるので、ちょっと謎です。わかる方教えてください。
アサート
アサートに使えるものは
should
assure
should_be
should_have
should_not
assure_not
should_not_be
should_not_have
がありますが、内部的には
should
should_not
の2つで、他は上記いずれかのエイリアスです。
アサーションのためにshould
あるいはそのエイリアスを使うにあたって、PASS時は特に困ることはなさそうです。
一方FAIL時は多少厄介で、TimeOutExceptionが出てきてしまいました。
たとえば、以下がFAIL時の表示の例です。画面に51000と表示されるべきところ、わざと「41000と表示されるか」をテストして失敗させています。
コード(抜粋)
s(by.id("price")).should(have.text('41000'))
結果(抜粋)
E selenium.common.exceptions.TimeoutException: Message:
E failed while waiting 4 seconds
E to assert Text
E for first_by('id', 'price')
E
E reason: ConditionMismatchException: condition did not match
E expected: 41000
E actual: 51000
E screenshot: file://.//screenshot/screen_1572244618378.png
..\..\..\..\appdata\local\programs\python\python37\lib\site-packages\selene\elements.py:232: TimeoutException
ConditionMismatchExceptionなのでそこ見ればわかるだろと言われればそうなのですが、エラーメッセージの最後の最後でTimeoutExceptionで出てきてしまうのがうーん。。
とはいえ、比較のときには標準のassert使う、だとラッパーライブラリのうまみ半減なので、難しいところですね。
また、標準のassertだと条件式がFalseのときだけ表示するメッセージを第三引数に書いておけますが、Seleneのアサートだとそれが無さそうです。
参考
- 公式
- 作者による紹介プレゼン資料
- Selenide alternative in Python
- こっちのほうがGitHubのREADMEよりわかりやすい
Author And Source
この問題について(PythonのSeleniumラッパーSeleneの使い方), 我々は、より多くの情報をここで見つけました https://qiita.com/YoshikiIto/items/0674631de996f3d52f14著者帰属:元の著者の情報は、元のURLに含まれています。著作権は原作者に属する。
Content is automatically searched and collected through network algorithms . If there is a violation . Please contact us . We will adjust (correct author information ,or delete content ) as soon as possible .