普段、Behat+Seleniumでテストしてて、特に使いにくくなったというワケではないんですが、最近Pythonはじめたのもあって、せっかくだしPythonで書こうと思い立ち、Selenium(Python)環境を作ってみました

環境

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
$ cat .python-version
3.5.2

$ cat requirements.txt
decorator==4.0.11
docutils==0.13.1
future==0.16.0
robotframework==3.0.2
robotframework-selenium2library==1.7.4
selenium==3.4.3

$ google-chrome --version
Google Chrome 59.0.3071.115

$ firefox-esr --version
Mozilla Firefox 52.2.0

セットアップ:インストール(robotframework-selenium2library)

Python3環境の場合、pipで落ちてくるrobotframework-selenium2libraryパッケージは、インストール時にSyntaxErrorが出て中断してしまうので

1
2
3
4
5
6
7
8
9
10
11
12
$ pip install robotframework-selenium2library
Collecting robotframework-selenium2library
Using cached robotframework-selenium2library-1.7.4.tar.gz
Complete output from command python setup.py egg_info:
Traceback (most recent call last):
File "<string>", line 1, in <module>
File "/private/var/folders/w6/rjdtmsb96ks4nv4xfm2p8v400000gp/T/pip-build-__rwphnc/robotframework-selenium2library/setup.py", line 7, in <module>
from ez_setup import use_setuptools
File "/private/var/folders/w6/rjdtmsb96ks4nv4xfm2p8v400000gp/T/pip-build-__rwphnc/robotframework-selenium2library/src/ez_setup.py", line 106
except pkg_resources.VersionConflict, e:
^
SyntaxError: invalid syntax

こちらのissueを参考にインストールしました

1
$ pip install -U https://github.com/HelioGuilherme66/robotframework-selenium2library/archive/v1.8.0b1.tar.gz

セットアップ:インストール(ブラウザ)

ChromeとFirefoxをインストール(参考:9zilla/include/browser.docker

1
2
3
# wget -q -O - "https://dl-ssl.google.com/linux/linux_signing_key.pub" | apt-key add -
# echo 'deb http://dl.google.com/linux/chrome/deb/ stable main' >> /etc/apt/sources.list.d/google-chrome.list
# apt-get update && apt-get install -y google-chrome-stable firefox-esr

セットアップ:Chromeのドライバ入手

Behat+Selenium Webdriverで受け入れテストの自動化をやってみたでダウンロードした物をそのまま使ってます

PATHの通ったところに置きます

セットアップ:Firefoxのドライバ入手

Behatはfirefoxのドライバは不要でしたが、gecko driver not foundとなるため、こちらから入手

PATHの通ったところに置きます

セットアップ:Xvfb起動

GUI環境がある方はこの工程は不要です

1
2
3
4
$ Xvfb :99 -screen 0 1920x1200x24 > /dev/null &

// 環境変数にディスプレイ番号セット
$ export DISPLAY=:99

テストを書く:ディレクトリ構成

こんな感じにしました レポートなどは.gitignoreへ書いてバージョン管理対象から除外してます

1
2
3
4
5
6
7
8
9
10
11
12
13
14
.
├── log.html ← ログ
├── output.xml ← 何か
├── report.html ← レポート
├── requirements.txt
├── selenium-screenshot-1.png ← スクリーンショット(カレントディレクトリでpybot実行時)
├── selenium-screenshot-2.png
├── selenium-screenshot-3.png
└── testcase
├── login
│   ├── login-admin.robot ← テストケースはここに
│   └── resource ← テストケースからincludeするResourceファイル格納先
│   └── login.robot
└── setting.robot ← 共通設定

テストを書く:共通設定(setting.robot)

Selenium2Libraryの指定と、スクショ保存みたいな汎用的なKeyword、その他共通設定を書くファイル

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
*** Settings ***
Documentation 共通設定
Library Selenium2Library

*** Variables ***
${browser} chrome
${sel_speed_short} 1
${sel_speed} 2
${sel_speed_long} 5
${empty}

*** Keywords ***

ページアクセス
[Arguments] ${request-uri}
Open Browser ${base-url}${request-uri} ${browser}
Maximize Browser Window
Set Selenium Speed ${sel_speed}
Select Window title=${title}

スクリーンショットを保存
[Arguments] ${fn}
Capture Page Screenshot filename=${fn}

ブラウザを終了
Close Browser

すべてのブラウザを終了
Close All Browsers

このファイルに指定してあるVariablesについて、例えばbrowserの値などは、Jenkinsなどでジョブを組む場合、コマンドラインから切り替えて使いたい場合があると思います

コマンドラインからVariableを指定するには、テスト実行時に--variable name:valueの形式でオプションをつけて実行します

1
2
$ pybot --variable browser:chrome ./testcase/login/login-admin.robot
$ pybot --variable browser:firefox ./testcase/login/login-admin.robot

テストを書く:キーワード(resource/login.robot)

このファイルは、後述のTestCaseからincludeするためのKeyword集みたいな感じにしていきます

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
*** Settings ***
Documentation ログイン

Resource ../../setting.robot

*** Keywords ***

HTTPSサイトへリダイレクトすること
Select Window url=https://hoge.example.com/admin/login/

ログインフォームの入力チェック
[Arguments] ${username} ${password} ${error1} ${error2}
Input Text css=form input[name='email'] ${username}
Input Text css=form input[name='password'] ${password}
Click Button id=doLogin
Element Should Contain css=form .error ${error1}
Element Should Contain css=form .error ${error2}
Capture Page Screenshot

テストを書く:テストケース(login/login-admin.robot)

Resourceが出来たら、Testcaseを作っていきます

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
*** Settings ***
Documentation 管理画面:ログイン

Resource ./resource/login.robot

*** Variables ***
${base-url} http://hoge.example.com
${title} ログインページ

*** Test Cases ***

ログイン画面にアクセス
ページアクセス /admin/login/
HTTPSサイトへリダイレクトすること

フォームの入力チェック
[Template] ログインフォームの入力チェック
${empty} ${empty} メールアドレスは必須です。 パスワードは必須です。
a ${empty} ${empty} パスワードは必須です。
${empty} a メールアドレスは必須です。 ${empty}
a a ログインに失敗しました ${empty}

[Teardown] Close All Browsers

最も基本的なテストケースの書き方は、「ページアクセス」のように、キーワードファイル(resource/login.robot)に作成したKeywordを並べて書いていきます

Robot Frameworkでは、半角スペース2つが区切り文字として識別されるため、引数を指定する場合は、半角スペース2つ以上を空けて指定します(タブを半角スペースにする設定=Vimだとexpandtab設定にしておくと書きやすいです)

「フォームの入力チェック」には、テストテンプレートを使用しています

さまざまな書き方が出来ますので、ここで紹介しているのはごく一部です。Selenium2Libraryマニュアルや、有志の方の和訳マニュアルを是非読んでみてください

テストを実行する

pybotコマンドを使って実行します

1
$ pybot ./testcase/login/login-admin.robot

実行後は、カレントディレクトリに、HTML形式のレポートなど、3つのファイル(log.html, output.xml, report.html)が出力されます

レポートの出力先などを変えたい場合は、以下の各オプションを実行時に指定します

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
$ pybot --help

Options
=======

-o --output file XML output file. Given path, similarly as paths given
to --log, --report, --xunit, and --debugfile, is
relative to --outputdir unless given as an absolute
path. Other output files are created based on XML
output files after the test execution and XML outputs
can also be further processed with Rebot tool. Can be
disabled by giving a special value `NONE`. In this
case, also log and report are automatically disabled.
Default: output.xml
-l --log file HTML log file. Can be disabled by giving a special
value `NONE`. Default: log.html
Examples: `--log mylog.html`, `-l NONE`
-r --report file HTML report file. Can be disabled with `NONE`

[おまけ] Vimmerの場合:.vimrc設定

Vim向けに素敵プラグインが公開されています → mfukar/robotframework-vim