rebotを用いRobotFrameworkの結果を編集する

#ターゲット
RF中級者向けの内容である

#概要
RobotFramework(RF)を用い自動検証・テストを実施する際、しばしば出力した html ログ・レポートを編集したいことがある。例えば、試験の中に流しすぎる項目を消すこと、実施失敗した試験項目だけやり直したい、全体レポートでまとめることなどが挙げられる。

一般的に、pybot（テスト実施）とrebotは以下の関係である

![](https://yuml.me/diagram/scruffy/class/[RFシナリオ]pybot->[xml],[xml]rebot->[最終html])




今回、あるプロジェクトで、試験で`SeleniumLibrary`でキャプチャした画像のURLを変えたい。具体的はこの状態である。

複数テストケースで実施して、`result_001`, `result_002` ... のようなフォルダーが作成された。各フォルダーの中にいつものRFの結果が `log.html` が作成され、その中に、`SeleniumLibrary`でキャプチャーされた画像が `href` で挿入されている。

各ログ`result_XXX/log.html` をブラウザーで開くと、正しくlogが確認されて、画像も表示されている。

| ![スクリーンショット 2019-08-24 16.26.00.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/310585/45ba393b-cfaf-40ee-6088-4bd3a2d5523a.png)|
|:-:|


次に、rebotを使い、すべての`result_XXX`のoutput.xmlをまとめ、一つのレポートファイルを作成する。

```shell:shell
rebot -d result result_001/output.xml result_002/output.xml result_003/output.xml
```

うまくいくようだったが、確認するとキャップチャーされた画像がうまく表示されていない。原因は、元々xmlの中に、画像の情報は各実行フォルダーに対する相対的なパスである。全体のlogファイルをrebotで作成された時、そのまま別フォルダー（`result`）に対する相対パスを使ってしまうので、画像のソースが正しくなくなった。

| ![スクリーンショット 2019-08-24 16.32.50.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/310585/296610dc-7720-2387-adaf-fd6646c7d3ef.png)|
|:-:|


rebotのマニュアルをよく見ると、各output.xmlの処理の`前後`にユーザの制御を入れられる。以下のようにrebotで実現したい。


>各キーワードの出力にあるimg src情報を親フォルダーに対する相対的なパスへ変更する


まず、このようなPythonクラス（modifier)を作成する。

```ruby:RebotRebaseImg.py
import re
from robot.api import SuiteVisitor
from robot.result.model import TestSuite
from robot.result.model import TestCase
class RebotRebaseImg(SuiteVisitor):
    """ Rebases embeded img in output with new `base`

    Rebased folder is extract from `Log Folder` meta of the suite
    Sample
    $ rebot  --prerebotmodifier ./RebotRebaseImg.py -N xxx -L info -d result result_001/output.xml
    """
    def __init__(self):
        self.base = None

    def start_suite(self,suite):
        if 'Log Folder' in suite.metadata:
            log_folder=suite.metadata['Log Folder']
            self.base = log_folder.replace('[','').replace(']','').split('|')[0]

    def end_message(self,msg):
        if msg.html and re.match(r'.*<img src=.*>.*',msg.message):
            new_msg = re.sub(r'="([^"]*?.png)"','="%s/\\1"' % self.base, msg.message)
            msg.message = new_msg
```
ポイントは２つある。一つ目は、`start_suite`はテストが開始する際、呼ばれている。このとき、meta dataを使い、ベース・フォルダーのパスを取得する。このやり方は、このケース限りであるが、他の手法（手動でも）ベース・フォルダーのパスを取得可能である。

二つ目は、`end_message`である。これはキワードが `終了する際、ログに書き出す前に` 呼ばれる。このように、`end_message`で渡されたパラメータ ``msg``をいじり、最終的にログに出力される情報を変更可能になる。

このクラス（modifier)を用い、もう一回rebotを実施する

```shell:shell
rebot --prerebotmodifier RebotRebaseImg.py -d result result_001/output.xml result_002/output.xml result_003/output.xml
```

結果として、全体まとめられた `result/log.html`にも、キャプチャーされた画像が正しく表示できるようになった。

※modifierの中に扱っている関数やクラスの内容についてマニュアルなどにはあまり書かれていない。その時、[msgの詳細](https://robot-framework.readthedocs.io/en/3.0/autodoc/robot.model.html#module-robot.model.message) は役に立つ。


#まとめ
rebotおよび `--prerebotmodifier`の使い方について説明した。特集なケースであるが、マニュアルとあわせ、rebotの使い方、とくに`--prerebotmodifier`を用い、最終ログを編集する方法は参考になると思う。


#参考
- [RFの概要](https://qiita.com/thinkAmi/items/a89bf2ef9a8bd975ea2f)
- [RF結果の後処理について](https://robotframework.org/robotframework/latest/RobotFrameworkUserGuide.html#post-processing-outputs)