🌤️

Jupyter NotebookとJenkinsで快適Selenium生活 - お試し編

2022/02/20に公開

ありがたいことに開発者として毎年いくつかのサービスの公開に関わらせていただいているのですが、リリースしたシステムがうまいこと動いているかが気になってしまい、基本的な死活監視やパフォーマンス監視は自分でしないと夜も眠れません。そんな中、いろいろ試してきた中でSelenium + Jupyter Notebook + Jenkinsの組み合わせがいい感じに死活監視できて睡眠時間確保に貢献してくれているので、その方法のご紹介を。

本記事では、Jupyter Notebookを使ったSeleniumスクリプトの作成方法と、JenkinsによるNotebookの定期実行方法を紹介します。ここではmybinder.orgを使う形で解説していますので、Docker等の計算機環境は不要でブラウザさえあれば試すことができます
なお、mybinder.orgは時間制限付きの環境ですので、継続的にこの定期実行環境を運用する方法については別の記事で紹介する予定です。

SeleniumとJenkinsとJupyter Notebookと

Webサービスを手っ取り早く死活監視したい、そんな時便利なのがSeleniumです。
Seleniumを使ったコードを記述して、Jenkinsで定期実行することで、定期的に状況を確認することが可能ですが、この方法には以下のような問題があります。

  • コードを記述するのが面倒 ... Seleniumを使ったテストの記述は、画面表示のタイミングや各ステップでどのような要素が表示されるかなど、ある程度試行錯誤的に行わなければならない。
  • ある日突然失敗するようになる ... 特に外部サービスに依存している場合など、当初の試行錯誤時には遭遇しなかった状況に陥りテストが失敗するようになることが多い。Seleniumを使ったテストやスクリーンキャプチャ等の取得を適切に記述していないと、このような状況での状況把握が難しい。

このような試行錯誤的なスクリプト作成、視覚的な状況把握に便利なのが Jupyter Notebook です。
Jupyter Notebookはデータ分析の用途でよく利用されるツールですが、Webブラウザを介してコードと説明(Markdown)を組み合わせたNotebookファイルを作成することができ、コードの実行結果をNotebook上に視覚的に残すことも可能です。

Jupyter Notebook実行画面

このように、Seleniumテストのステップごとに適宜ブラウザ画面を表示するようにすれば、失敗時はNotebookファイルを参照することでなぜ失敗したかのヒントとすることもできます。

また、Jupyter Notebook自体は定期実行のような機能を持ちませんので、Jenkinsを併用します。Jupyter NotebookはWebブラウザからの実行を想定した環境ですので、papermillというツールを用いてNotebookをコマンドラインで実行することで、Jenkinsからの定期実行を実現します。

環境の準備 - Webブラウザだけで試してみる

簡単にJupyter Notebookの動作を試すには、mybinder.orgが便利です。時間制限付きではありますが、無償で実行環境なしにJupyter Notebook環境を試すことができます。

今回の記事に必要なソフトウェアを含むJupyter Notebook環境を実行するには、以下のリンクをクリックしてください。

jupyter-with-jenkins

しばらく待つと、以下のようなJupyter Notebookの画面が表示されます。この環境はmybinder.orgの環境で実行され、時間限定ながら自由に利用することができます。

Jupyter Notebook画面

この環境は GitHub:yacchin1205/jupyter-with-jenkins によって定義しています。
国立情報学研究所のクラウド運用チームが作成しているイメージをベースに、SeleniumやJenkins等のツールをインストールしています。どんなツールをインストールしているかは Dockerfile を参照してください。

mybinder.orgでの環境起動は launch binderボタン からも可能です。

launch binderボタン

Jupyter NotebookでSeleniumを使う

Jupyter Notebookの画面が開いたら、Notebookファイル Using Selenium.ipynb をクリックします。このNotebookファイルには、GitHubのURLを開いて、画面キャプチャを撮るという単純な例を記述しています。

Notebook一覧

Notebookを実行する

Notebookを開くと、コードと説明が表示されます。スクリプトが記述されたセル(コードセル)をマウスクリックして選択したのち、Run ボタンでスクリプトを実行することができます。説明を読みながら、順番にコードセルを実行していってください。

Notebook画面

なお、この環境には国立情報学研究所のクラウド運用チームが作成しているJupyter拡張がインストールされています。例えば、一度実行したセルにはフリーズマークが表示され、2回目は実行できなくなります。再度実行したい場合は、凍結解除して実行し直してください。
操作方法については、NII謹製の機能拡張について を参考にしてください。

コードセルを記述する: URLを開く例

このNotebookではGitHubのページをSeleniumを使って開いています。
例えば以下のスクリプトはSeleniumのWebDriverに対して https://github.com/yacchin1205/jupyter-with-jenkins を開くことを指示することで、WebDriverが管理するブラウザにてそのURLを開きます。その結果ブラウザに表示された画面をJupyter Notebookに表示しています。

url = 'https://github.com/yacchin1205/jupyter-with-jenkins'
driver.get(url)

# Output the screenshot
driver.save_screenshot(os.path.join(work_dir, 'sample.png'))
Image(os.path.join(work_dir, 'sample.png'))

これを実行すると以下のようにコードセルの下に画面出力が表示されます。

画面出力

続くコードセルのように、WebDriverから画面上の要素を取得し、click等のイベントを発生させていくことで、Selenium上でブラウザ操作を機械的に再現することができます。
適当なステップごとに画面出力を行っていくことで、試行錯誤的にスクリプトを記述していくことができます。

コードセルの追加方法やSeleniumのコード記述方法などはドキュメントや解説を検索してみてください。実際の画面出力を見ながらのスクリプト記述は、一般的なスクリプトエディタによる作成方法に比べて楽なのではないかと思います。

パフォーマンス情報を記録する

とりあえず一通りテストが通っても、まだまだ心配なことはあります。その一つが応答時間です。
例え機能的に正しく動いていたとしても、本来100msec程度での応答を期待しているところが5秒を超えていたりするとちょっと心配になってしまったりします。

そんな時のために、harファイルとしてリクエスト記録を取っておきましょう。
Seleniumでブラウザに依存せずharファイルを取得する手法は定義されていなかったようですので、ここではChromeを例に実装しています。

Using Selenium.ipynb Notebookの 4 応答速度確認 を実行してみてください。harファイルを継続的に取得しておくことで、性能上のトラブルが発生した際にも遡って問題が起き始めたタイミングなどを把握できるかもしれません。

Jenkinsで定期実行を行う

ここまででJupyter Notebook上でSeleniumを扱う方法について解説しました。
次に、このように作成したSeleniumを使ったJupyter NotebookをJenkinsで実行する方法についてみていきます。

Jenkinsは、mybinder.org上に立ち上げた環境に自動的にインストールされています。
New - Jenkinsメニューをクリックすると、同じコンテナ中で動作しているJenkinsの画面が表示されます。

jenkinsメニュー

mybinder.orgでのJupyter Notebook起動直後はJenkinsへのリダイレクトで失敗(Service Unavailable)する場合があります。失敗する場合はしばらく待ってみてください。

papermillで実行してみる

Jenkinsではシェルコマンドを介してJupyter Notebookを実行します。
まずはJupyter Notebookのターミナルから、papermillコマンドを使ってJupyter Notebookを実行してみましょう。

ターミナルは以下のNew - Terminalメニューから開くことができます。

Terminalメニュー

すると、コマンド入力プロンプトが現れますので、以下のコマンドを入力します。

papermill "Using Selenium.ipynb" Output.ipynb

papermillコマンドは、第1引数に指定されたNotebookファイルを実行し、第2引数に指定されたNotebookファイルとして結果を保存することができます。実行すると、進行状況を示すバーが表示され、Output.ipynbに実行結果が保存されます。
Output.ipynbを開いて、Seleniumによるスクリーンショットなどが保存されていることを確認してください。この出力NotebookファイルをJenkinsジョブ実行のたびに保存しておけば、失敗した場合に何が原因で失敗したかのヒントを得ることができます。

定期実行ジョブを作成する

Jenkinsの画面からジョブを作成します。通知の設定方法などは詳しいWebサイトに譲るとして、papermillコマンドを定期的に実行したい場合は以下のように入力します。

Jenkinsの画面を開き、新規ジョブの実行を選択し、フリースタイル・プロジェクトとしてジョブを作成します。

新規ジョブの作成

ジョブを作成したら、そのジョブの設定画面を開き、ビルド・トリガに 定期的に実行 を、ビルド手順に シェルの実行 を選択し、以下のように入力します。

ジョブの設定

定期的な実行の頻度は上の例では15分ごととしていますが、テストの内容に応じて適切なタイミングを設定してください。
また、シェルスクリプトには以下のように、実行したいNotebookのファイルパスと、出力先のNotebookファイルパスを指定します。

cd /home/jovyan
papermill "Using Selenium.ipynb" "${WORKSPACE}/Using Selenium-${BUILD_ID}.ipynb"

${WORKSPACE}, ${BUILD_ID}はJenkinsによって実行しているジョブ情報、ビルド情報にしたがって置き換えられます。このようにすることで、実行結果はJupyter Notebook環境中の jenkins-workspace ディレクトリに実行ごとに別ファイルとして保存することができます。

jenkins-workspaceディレクトリ

あとは失敗時の通知として、Slack等の送信先を指定すれば、定期的にNotebookファイルを実行し、失敗したら通知してくれる環境の出来上がりです!

まとめ

Jupyter Notebookを利用することで、Seleniumのような試行錯誤を含むスクリプトの作成を視覚的に行うことができ、作成したNotebookはpapermillを介してJenkinsで自動実行できることを、実際にお試しできる mybinder.org での実行例として紹介しました。

今回はお試しということで mybinder.org で実行しましたが、この環境は短時間で削除されてしまいます。次回は、自身が持っているマシンやパブリッククラウドで同様の環境を実行し、監視Notebookを実行する方法について紹介したいと思います。

Discussion