Robot drives on the web: Robot Framework & Selenium2Library

# はじめに
この記事は Selenium/Appium Advent Calendar 2014の10日目の記事です。昨日の記事は @isaac-otao さんの[「Selenium WebDriverのカスタマイズ事例」](http://qiita.com/isaac-otao/items/d6e3d5d3cecd23cce77b)でした。

# Robot Frameworkとは
[RobotFramework](http://robotframework.org/)(以下、RF)はオープンソースとして公開されている、Python製のTest Automationフレームワークです。
RF本体はOS非依存の汎用的なフレームワークです。RFのテストケースは、テキストファイル上にキーワードを表形式で記述していく、キーワード駆動型のもので、インストールパッケージに含まれる標準キーワードライブラリに加え、今回取り上げるSelenium2用のものをはじめ、豊富な外部ライブラリが公開されています（試したことないけど、appium-libraryなんてのもある）。
また、自分でキーワードを新規に作るのも簡単にできて、標準ライブラリを含め、ありもののキーワードは当然のように英語ベースですが、自作のキーワードは日本語で記述することも可能です。ちょっとロジックが込み入ったモノを作りたい場合、Pythonで実装したクラスを簡単にキーワードとして取り込むことも可能です（今回の記事では触れませんが）。
今回はRFとSelenium2のPythonバインディングをラップした[Selenium2Library](https://github.com/rtomac/robotframework-selenium2library/)(以下、Se2Lib)を使ってみたよ、という記事になります。

# 前提
RF自体は、

*  OSとしては、Windows, Mac, Linux
*  Pythonのバージョンは2.5～2.7(RF2.5～2.8)、 2.6,2.7,3.3以降(RF3.0以降)
*  Python処理系としてはCPython, Jython, IronPython

をサポートしています。
が、今回は以下の環境で確認しています(とはいえ、環境依存の機能は使ってないはず)。

| 環境 | バージョン |
| ---- | ---------|
| OS | Win 8.1(x64) |
| Python | CPython 2.7.8 |
| RF | 2.8.6 |
| Selenium2 | 2.44.0 |
| Se2Lib | 1.6.0 |
| Browser | Firefox 34.0 |


ちなみに2014/12/10時点でPython3.x系には未対応です。
過去のRFのML上のやりとりを見ると、Pythonの2.5系のサポートが不要になったら、3.x系も正式サポートしたいということでした。でも、Jythonでは2.5系が現役で、2.7系はまだベータ段階なのであと1,2年は3.x系は正式サポートされないんじゃないだろうか。。。

(2017/4/19追記)
2015/12/31にリリースされた、RF3.0でPython3.xに対応しました。RF3.0.xは、Python2.6,2.7,3.3以降をサポートしており、RF3.1でPython2.6のサポートがなくなる予定です。

# インストール

RF, Se2Libとも、PyPIで公開されています。Se2Libをpipでインストールすれば、依存ライブラリになっているRFとSelenium2のPythonバインディングも一緒にインストールされます。

```
> pip install robotframework-selenium2library
```

RFのみインストールしたいなら、以下でインストールできます。

```
> pip install robotframework

```
また、RFには標準でテストライブラリのソースからHTMLドキュメントを出力してくれる libdoc というツールが付属しているのですが、インストール済みのライブラリをローカルドキュメントサーバ化してくれる、 robotframework-hub(rfhub)というツールが公開されているので、こちらも入れておきます。

```
> pip install robotframework-hub
```
rfhubの起動は以下のようにします。

```
> python -m rfhub
```

デフォルトでは7070ポートでサーバが立ち上がるので、ブラウザで http://localhost:7070 にアクセスすると、次のような画面になります

![ダッシュボード画面](https://qiita-image-store.s3.amazonaws.com/0/48132/f718ebb4-010a-e680-b62c-27b33d05bb86.png)

[Click to go to keyword documentation]をクリックすると次の画面になります。
![selenium-screenshot-2.png](https://qiita-image-store.s3.amazonaws.com/0/48132/ee801af8-bb38-6fcc-1b39-6fc5bb7be0c5.png)


画面右上の検索ボックスからキーワードの検索も可能です。
今回はRF+Se2Libを使ったテストケースの対象アプリとして、このrfhubをテストしてみます。

# テストケースの書き方
## ファイルフォーマット
テストケースはテストケースファイルに記述します。

RF自体はテストケースのファイルフォーマットとしてHTMLやTSVなど、いくつかの形式をサポートしていますが、今回は一番シンプルなプレーンテキスト形式で説明します。

RFでは、テストケースをキーワード＋引数をベースとしたテーブル形式で記述しますが、プレーンテキスト形式では、行内における列間のセパレータとしては、スペース2個以上、またはパイプ文字('|')を使用します。セパレータについては、今回の記事ではスペース4個(Pythonのインデント標準)をセパレータとして使用します。ファイルエンコードはUTF-8で保存してください。

テストケースファイルは以下の複数のテーブルから構成されます。

| テーブル名              | 用途 | 別名 |
| --------------------- | ---------|----- |
| Setting テーブル   | ライブラリやリソースをインポートする、などテストケースファイル内の環境設定情報を定義する | Setting, Settings, Metadata |
| Variable テーブル   | テストケースファイル内で使用する変数を定義する | Variable, Variables |
| Testcase テーブル  | テストケースを記述する | Test Case, Test Cases |
| Keyword テーブル | ユーザーキーワードを定義する | Keyword, Keywords, User Keyword, User Keywords |


VariableテーブルやKeywordテーブルは他のファイルに定義し、リソースファイルとしてテストケースのSettingテーブルに指定することでインポートすることができます。

## テストケースの記述
細かい説明をするときりがないので、今回はいきなりサンプルを紹介します。
以下のように、具体的な操作はキーワードにくくりだして、別ファイルに定義することができます。
その他のポイントを挙げてみると、

*  Setting テーブルのDocumentationは結果レポートにも出力されるので、ちゃんと書いておくのがよいです。
*  SettingテーブルにTest Setup、Test Teardownを宣言しておくと、テストケースごとにここに記述したキーワードを前処理、後処理として実行してくれます。
*  今回は１つだけですが、Resourceで複数のキーワードファイルをインポート可能です。
*  引数埋め込み型のキーワードも定義可能です。"firefox" や"Screenshot" は実はキーワードの引数です！

```text:rfhub_test.robot
*** Settings ***
Documentation    Selenium/Appium Advent Calendar 2014 Day10
...    Robot Drives On the Web: RF+Se2Lib テストケースサンプル
Resource    rfhub_keywords.robot
Test Setup    RF-hubを起動する
Test Teardown    RF-hubを停止する

*** TestCases ***
標準ライブラリが表示されることのテスト
    RF-hubのトップページを firefox で表示する
    キーワードドキュメントページに移動する
    標準ライブラリのドキュメントが表示されること

標準ドキュメントのキーワードが検索可能なことのテスト
    RF-hubのトップページを firefox で表示する
    キーワードドキュメントページに移動する
    キーワード Screenshot で検索がヒットすること

```

次がユーザーキーワードを定義したファイル。
ここではRFの標準ライブラリの1つである ProcessとSe2Libのキーワードを使用しています。
自明なものをのぞき基本的にDocumentationは書きましょう。ユーザーキーワードもHTMLドキュメント化可能です。

サンプルで使用しているキーワードは以下の通りです。詳細はそれぞれのドキュメントにあたってください。

| ライブラリ名 | キーワード | 引数 | 説明 |
| ------------- | ------------ | ------| ------|
| Process | Start Process | command, *arguments, **configuration | バックグラウンドでプロセスを起動します |
|  | Terminate Process | handle=None, kill=False | プロセスを停止します |
| Selenium2Library | Open Browser | url, browser=firefox, alias=None, remote_url=False, desired_capabilities=None, ff_profile_dir=None | 指定されたURLでブラウザを起動します |
| | Close Browser | | ブラウザを終了します |
| | Capture Page Screenshot | filename=None | 現在のページのスクリーンショットを取得し、ログに埋め込みます |
| | Click Element | locator | locator で指定した要素をクリックします |
| | Input Text | locator, text | locator で指定したテキストフィールドに指定した text を入力します |
| | Page Should Contain | text, loglevel=INFO | 指定した text を現在のページが含むか確認します |
| | Page Should Contain Element | locator, message=, loglevel=INFO | locator で指定した要素をページが含むか確認します |
| | Wait Until Page Contains Element| locator, timeout=None, error=None | 現在のページ上に locator で指定した要素が表示されるまで待ち合わせます |

locatorの指定の仕方は以下の通りです。
SeleniumのPythonバインディングだとAPIを使い分ける必要がありますが、同じキーワードで、locatorの指定の仕方で使い分ける、という感じです。

| Strategy  | 例  |
| --- | --- |
| idかname | Click Element    identifier=my_element |
| id         | Click Element    id=my_element |
| name       | Click Element      name=my_element  |
| xpath      | Click Element      xpath=//div[@id='my_element'] |
| dom        | Click Element      dom=document.images[56] |
| link       | Click Element     link=My Link          |
| partial link | Click Element    partial link=y Lin  |
| css        | Click Element     css=div.my_class      |
| jquery     | Click Element    jquery=div.my_class   |
| sizzle     | Click Element    sizzle=div.my_class   |
| tag        | Click Element    tag=div               |

```text:rfhub_keywords.robot
*** Settings ***
Documentation    RF-hubテスト用キーワード
Library    Process
Library    Selenium2Library

*** Variables ***
${base_url}    http://localhost:7070

*** Keywords ***
RF-hubを起動する
    ${handle}=    Start Process    python    -m    rfhub    .

RF-hubを停止する
    Terminate Process
    Close Browser

RF-hubのトップページを ${browser} で表示する
    [Documentation]    ${browser} に指定可能なブラウザ名は Se2Lib ドキュメントの
    ...    Open Browser キーワードの項を参照
    Open Browser    ${base_url}    ${browser}
    Page Should Contain Element    css=.container>h1

キーワードドキュメントページに移動する
    Click Element    css=.btn.btn-primary.btn-lg

標準ライブラリのドキュメントが表示されること
    [Documentation]    Builtin ライブラリの説明の文章がページに存在すればOKと
    ...    判断する
    Page Should Contain    An always available standard library with often needed keywords.
    Capture Page Screenshot    # エビデンスとしてスクリーンショットをとっておく

キーワード ${keyword} で検索がヒットすること
    [Documentation]    検索ボックスに${keyword}で指定したキーワードを入力後、
    ...    検索結果テーブルが表示されたらヒットと判断する。
    Input Text    css=#search-pattern    ${keyword}
    Click Element    css=.btn.btn-default
    Wait Until Page Contains Element    css=#keyword-table
    Capture Page Screenshot    # エビデンスとしてスクリーンショットをとっておく

```
# テストケースの実行とレポート
テストケースはpybot コマンドで実行します。フォルダを指定すると、そのフォルダ下のすべてのテストケースファイルを実行することができます。

```
> pybot rfhub_test.robot
```
コンソールには以下のように出力されます。

![console.PNG](https://qiita-image-store.s3.amazonaws.com/0/48132/5d0f7d0f-3afb-1876-904e-487534b1e4c5.png)

HTML形式のレポートとログも出力されます。
今回はテストケースにタグをつけてませんが、タグをつけておくと、タグごとの集計結果も出力してくれます。

![report.png](https://qiita-image-store.s3.amazonaws.com/0/48132/817c5c1a-40d6-2f85-8605-80764a05c8ca.png)
![log.png](https://qiita-image-store.s3.amazonaws.com/0/48132/c2ad838a-7215-7c1e-4342-3afee925fa89.png)

# まとめ
テストケースファイルのフォーマットがシンプルで、他のテストフレームワークに比べても、非プログラマでも抵抗なく書けるフレームワークなんじゃないかと思います。
足りない部分はRFのキーワードの組み合わせだけではなくて、Pythonのモジュールも簡単に取り込んでキーワードとして扱えるので、テストケース自体の設計と自動化の部分の設計の役割分担もうまくできるんじゃないかと思います（まぁ、実際にやってみるといろいろ問題はでますが）。

今回の記事は、ちょっとはしょりすぎた気がしますが、今回書けなかった情報も少しずつ別記事で書いていけたらいいなと思います。
RFについては、日本語の情報がほとんどない状態なので、今回の記事で興味を持った方は是非試してもらって情報共有してもらえるとうれしいです！

明日は@TakesxiSximada さんです！

# 参考
* RF公式: http://robotframework.org/
* RFユーザーズガイド: http://robotframework.org/robotframework/latest/RobotFrameworkUserGuide.html
* Se2Libリポジトリ: https://github.com/rtomac/robotframework-selenium2library/
* RF-hubリポジトリ: https://github.com/boakley/robotframework-hub
* Robot Framework + Selenium2Libraryで簡単受け入れテスト: http://www.ryuzee.com/contents/blog/5933