Robot Framework + Selenium2Libraryで、リファラを書き換えるChrome拡張をWebDriverに入れてテストする

リファラによって挙動が変わるWebアプリをRobot Frameworkでテストすることがありました。

Webアプリのコードを書き換えたくないため、なにか良い方法がないかを探したところ、

を組み合わせれば良さそうでした。

その時に試した内容をメモしておきます。

 
2017/9/2追記

Selenium2Libraryですが、バージョン3からは SeleniumLibrary へと名称が変更されています。詳しくはこちらに書きました。
RobotFrameworkのSelenium2Libraryの名前が、SeleniumLibraryへと変更されてた - メモ的な思考的な

なお、本文はSelenium2Libraryのままにしてあります。

2017/9/2追記ここまで

 
目次

 

環境

 

Seleniumで開くChromeDriverに拡張を入れる 

packedとunpacked、どちらの方式の拡張を入れるか

Seleniumで使うChromeDriverに拡張を入れる方法は、ChromeDriverの公式サイトにありました。
Chrome Extensions - ChromeDriver - WebDriver for Chrome

方法としては、

の2つがあるようです。

紹介されているコードはJavaっぽいため、Pythonのコードを探したところ、前者については以下などがありました。
google chrome - Running Selenium WebDriver using Python with extensions (.crx files) - Stack Overflow

一方、後者のDesiredCapabilitiesオブジェクトの setCapability() メソッドを使う方法を調べてみましたが、それらしい事例はなく、Pythonライブラリのソースコードにもそれらしいメソッドは見当たりませんでした。
selenium/desired_capabilities.py at master · SeleniumHQ/selenium

そこで今回は、前者の crxファイルを使う方法で実装することにしました。

 

packedな拡張を作成する方法

Chrome拡張がどこにインストールされるかを調べたところ、 ~/Library/Application Support/Google/Chrome のようでした。
User Data Directory

また、Chrome拡張のID(ディレクトリ名)は、以下を参考にして確認しました。
Google Chrome のアプリや拡張機能、テーマが保存されている場所 - Qiita

そのディレクトリを見たところ、unpackedな状態だったため、何らかの方法で crxファイルを取得する必要がありました。

 
調べてみたところ、以下のページにpackedな拡張の作り方が記載されていました。
CRX Package Format - Google Chrome

ただ、pemファイルを用意するなどの手間がかかりそうなため、もっと容易な方法を探してみたところ、Chrome拡張のページからcrxファイルを取得するChrome拡張 Get CRX がありました。
Get CRX - Chrome ウェブストア

試しに Referer Control のページで使ってみたところ、crxファイルが取得できました。

今回はそのファイルを、テストを実行するディレクトリ直下に referer_control.crx として保存します。

 

Robot Frameworkで実装する

HeadlessなChromeだとChrome拡張ページが開けないため、今回は普通のChromeを使って実装します。

${options} =  evaluate  sys.modules['selenium.webdriver'].ChromeOptions()  sys

# HeadlessだとChrome拡張ページが開けない
# call method  ${options}  add_argument  --headless

# ${OUTPUT DIR}は、テストを実行するディレクトリ
call method  ${options}  add_extension  ${OUTPUT DIR}/referer_control.crx
create webdriver  Chrome  chrome_options=${options}

 

Referer Controlでリファラを書き換える

上記のままではChrome拡張を入れるだけで何も設定がされないため、Referer Controlの設定を行います。

 

Referer Controlの設定方法を調べる

以下が参考になりました。
Chromeでリファラ偽装する方法(リファラコントロールの使い方)

 

Robot Frameworkで実装する

上記の通り、Referer Controlの設定はブラウザから行うため、Robot Frameworkで実装できそうでした。

Robot Frameworkのlocatorに何を使うか悩みましたが、Chrome拡張のHTMLはそれほど変わらないだろうと考えました。

そこで、Chrome Developer Toolを使ってXPathを取得し、それをlocatorとして使いました。*1

あとは、Robot Frameworkで実装します。

今回は http://localhost:8084/referer/target というURLの場合のみ、リファラhttps://www.google.co.jp へと書き換えるようにしました。

# 「Referer Control」拡張の設定ページを開く
go to  chrome-extension://hnkcfpcejkafcihlgbojoidoihckciin/chrome/content/options.html

wait until page contains element  xpath=//*[@id="settingsTable"]/tbody/tr/td[2]/input
click element  xpath=//*[@id="settingsTable"]/tbody/tr/td[2]/input

# site filterに入力する
# 今回は、「http://localhost:8084/referer/target」というサイトであればリファラを書き換える
input text     xpath=//*[@id="settingsTable"]/tbody/tr/td[2]/input  http://localhost:8084/referer/target

# Customボタンを押す
click element  xpath=//*[@id="settingsTable"]/tbody/tr/td[8]

# Custom refererを入力する(Googleから来たことにする)
# 1秒待たないとうまくいかない
sleep  1s
input text  xpath=//*[@id="settingsTable"]/tbody/tr[5]/td[2]/table/tbody/tr[1]/td[1]/input  https://www.google.co.jp

# 適当なところをクリックして保存
click element  xpath=//*[@id="settingsTable"]/tbody/tr/td[2]/input

 

Bottleアプリの実装と動作確認

Bottleアプリの実装

上記のRobot Frameworkのテストコードが正しく動作するかを確認するため、Bottleアプリを作成して動作を確認します。

今回は、単純にリクエストヘッダの Referer を表示するだけにします。

target.py

@get('/referer/target')
@get('/referer/exclude')
def get_referer_target():
    referer = request.get_header('Referer')
    return f'<p id="referer">Referer: {referer}</p>'

 

Robot Frameworkで動作確認するコードを実装

先ほどのChrome拡張の設定に続いて以下のコードを書きます。

# リファラが書き換わるページへアクセス
go to  http://localhost:8084/referer/target
${target} =  get text  id=referer

# リファラが書き換わらないページへアクセス
go to  http://localhost:8084/referer/exclude
${exclude} =  get text  id=referer

# 検証してブラウザを閉じる
log to console  ${EMPTY}
log to console  ${target}
log to console  ${exclude}
should not be equal  ${target}  ${exclude}
close browser

 

動作確認

テストがパスしました。Chrome拡張の設定がうまくいき、リファラが書き換わっているようです。

$ robot selenium_modify_referer_test.robot 
===================================
Selenium Modify Referer Test                   
===================================
Chrome拡張でリファラを書き換えるテスト                                
Referer: https://www.google.co.jp
Referer: None
Chrome拡張でリファラを書き換えるテスト | PASS |
...

 

その他参考

Firefoxを使う場合

Firefoxを使う場合の例が以下にありました。
webdriver - setting request headers in selenium - Stack Overflow

 

Chromeコマンドライン・オプション

以下にまとまっていました。
List of Chromium Command Line Switches « Peter Beverloo

 

OpenSSLでのpemファイル作成

もしpemファイルを作る場合は、以下を参考にします。
ssl - How to create a self-signed certificate with openssl? - Stack Overflow

 

ソースコード

GitHubに上げました。 selenium2_library_sample/tests/selenium_modify_referer_test.robot ファイルが今回のテストファイルです。
thinkAmi-sandbox/RobotFramework-sample: Robot Framewrok samples

*1:該当Element上で右クリック、Copy > Copy XPathXpathを取得できます