エディタやIDEのRobot Frameworkプラグインについて

この記事は「Robot Framework Advent Calendar 2017 - Qiita」の12日目の記事です。

 
Robot Frameworkのテストケースはプレーンテキスト(.robot.txt)で書けるため、任意のエディタやIDEを使えます。

ただ、効率的にテストケースを書くためには、

  • シンタックスハイライト
  • キーワード補完
  • キーワードや変数の定義へジャンプ

などが欲しいです。

Robot Frameworkの公式サイトの Tools > Editor では、エディタやIDEプラグインについて紹介されています。
http://robotframework.org/#tools

そこで今回は、その中から

を試してみました。

 
目次

 

環境

 
ちなみに、自分は普段JetBrains系のIDEを使っているため、プラグインintellibot を使っています。

 

注意:SeleniumLibraryの補完について

2017/12/12現在、SeleniumをRobot Frameworkから扱う SeleniumLibrary の最新版(3.0.1)を参照した場合、JetBrains系のIDEVisual Studio Codeのプラグインではキーワード補完がうまく動作しないです*1

Selenium2Library 1.8.0 であればキーワード補完ができるようです。が、Python3.x系では動作しないです...

 

JetBrains系IDEプラグイン

3つのプラグインがありました。

このうち、 Robot PluginJava向けらしく、今回は試しませんでした。

 

Robot Framework Support (robot-plugin)

手元の環境で試したところ、

ができました。

一方、

がありました。

 

IntelliBot

手元の環境で試したところ、

  • シンタックスハイライト
  • キーワード補完
    • 標準ライブラリや、ユーザ定義のキーワード(日本語のキーワードもOK)
  • 定義へのジャンプ

などができました。

一方、

という問題がありました。

とはいえ、日本語のキーワード補完もできるので、こちらを使っています。

 
また、intelliBotにはオプション設定がいくつかあります。自分の場合はデフォルト設定に加え、Robot Frameworkのサンプルの書式に合わせ、 Capitalize Keywords にチェックを入れています。

これにより、 should be equalShould Be Equal として補完されます。少々挙動が怪しいですが、許容範囲内です。

 

Visual Studio Codeのプラグイン

現在は4つほど見つかりました。

Robot Framework Intellisense

手元の環境では

ができました。

一方、

  • 実装されているはずのコード補完やコードジャンプが効かない

がありました。

その他の既知の問題については、以下に記載がありました。
https://github.com/tomi/vscode-rf-language-server/blob/master/client/KNOWNISSUES.md

 

robotframework

手元の環境では

ができました。

コード補完やコードジャンプの機能は元々無いようです。

 

robot framework language

手元の環境では

ができました。

 

RobotF Extension

手元の環境では

  • 英語のキーワードを補完
  • 英語のキーワードの定義へ移動
  • 英語のキーワード名を置換

などができました。

一方、日本語については上記の機能が実行できませんでした。

また、シンタックスハイライトについては機能は実装されていないようです。説明にも、

You need to have robotframework language support for visual studio code if you want text highlighter

とありました。

 

Atomプラグイン

Atomプラグインを見たところ、階層的な依存が見られたため、すべてを入れてみます。

なお、インストール方法はこちらを参考にしました。
https://gist.github.com/Tset-Noitamotua/22e9edaade89e52fb10fcefd51a4547b

$ apm install language-robot-framework
$ apm install autocomplete-robot-framework
$ apm install hyperclick
$ apm install hyperclick-robot-framework

 
試してみたところ、

ができました。

一方、

  • 日本語のコード補完
  • キーワード定義へのジャンプ

ができませんでした。

 

その他

以下にも情報がありました。

 
ここで紹介した以外にも、エディタやIDEのRobot Frameworkのプラグインがあるため、いろいろと試してみてはいかがでしょうか。

シンタックスハイライトがあるだけでも分かりやすくなります。

*1:後述の通り、Atomプラグインでは動作しました

Robot Frameworkの変数ファイルについて

この記事は「Robot Framework Advent Calendar 2017 - Qiita」の10日目の記事です。

 
前回、Robot Frameworkにおける変数定義と優先順について書きました。

そこでは 変数ファイル については省略していたため、今回は変数ファイルについて記載します。

 
目次

 

環境

  • Robot Framework 3.0.2

 

変数ファイルとは

公式ドキュメントではこちらに記載があります。

 
Robot Frameworkでは、Pythonで書いた

をRobot Frameworkの変数として扱えます。それらが書かれたファイルのことを変数ファイルと呼びます。

Pythonで書けるので、リソースファイルと比べて柔軟な定義ができます。

 
今回はユーザガイドに従い、いろいろと試してみます。

 

変数ファイルをテストケースファイルで読み込むには

テストケースファイルのSettingsで Variables を使い変数ファイルを指定します。

以下の例では、テストケースファイルと同じディレクトリにある variable_file.py を変数ファイルとして読み込み、Robot Frameworkの変数として追加します。

*** Settings ***
Variables    variable_file.py

 

いろいろな変数ファイル中の定義

変数ファイルではいくつかの方法でRobot Framework用変数を定義できます。

 

Pythonの変数(定数)

Pythonファイルに

FOO = 'foo'

Pythonの変数(定数)を定義すると、Robot Frameworkの変数となります。

テストケースを

*** Test Cases ***
Pythonの定数
    log to console  ${FOO}

として実行すると、

Pythonの定数    foo

と出力されます。

 

Pythonの辞書

Pythonの辞書も同様です。

BAR = {'ham': 'spam'}

と変数ファイルを定義します。

テストケースを

Pythonの辞書
    log to console  ${BAR}

として実行した場合、

Pythonの辞書    {'ham': 'spam'}

Robot Frameworkの辞書型の変数となります。

 

Pythonの辞書で、定数名にプレフィックスを付けた場合

Pythonの辞書型変数名にプレフィックスを付けると、明示的に辞書型の定数として定義できます。

プレフィックス__変数名 という形であり、Robot Frameworkではプレフィックスが取れた変数名として認識されます。

以下の例の場合、Robot Frameworkでは BAZ として認識されます。

DICT__BAZ = {'egg': 'spam'}

 
また、プレフィックスを付けると、Robot Frameworkで . を使ったアクセスができます。

プレフィックスの有無での挙動を比較するため、それぞれの辞書を用意します。

BAR = {'ham': 'spam'}
DICT__BAZ = {'egg': 'spam'}

テストケースを

Pythonの辞書でプレフィックス無しの場合keyアクセスができない
    log to console  ${BAR.ham}

Pythonの辞書でプレフィックス付の場合keyアクセスができる
    log to console  ${BAZ.egg}

として実行した場合、

Pythonの辞書でプレフィックス付    {'egg': 'spam'}
Pythonの辞書でプレフィックス付    | PASS |
------------------------------------------------------------------------------
Pythonの辞書でプレフィックス無しの場合keyアクセスができない    | FAIL |
Resolving variable '${BAR.ham}' failed: AttributeError: 'dict' object has no attribute 'ham'

となります。

 

プレフィックスがないと変数名が重複する場合

Pythonではプレフィックスを付けた変数と付けない変数は別モノとなるため、重複していることに気づかないかもしれません。

例えば、Pythonコード中に以下を書いていたとしてます。

DICT__DUPLICATE = {'dup': 1}
DUPLICATE = {'dup': 2}

テストケースを

変数が重複していた場合
    log to console  ${DUPLICATE}

として実行した場合

変数が重複していた場合    {'dup': 1}

となります。

最初に定義されていたPythonの変数がRobot Frameworkの変数として使われます。

 

Pythonの関数の戻り値

Pythonの関数の戻り値をRobot Frameworkの変数として設定することもできます。

def get_result():
    return 1


RESULT = get_result()

テストケースで

Pythonの関数の結果を設定した変数
    log to console  ${RESULT}

として実行した場合

Pythonの関数の結果を設定した変数    1

となります。

Pythonの関数そのもの

Pythonの関数そのものも、Robot Frameworkの変数として定義できます。

def get_random():
    return random.randint(0, 20)

テストケースにて

Pythonの関数そのもの
    log to console  ${get_random}

として実行した場合、

Pythonの関数そのもの    <function get_result at 0x10650d400>

となります。

 

アンダースコアで始まるPythonの関数

関数名が _ から始まる場合、Robot Frameworkの変数としては使えません。

def _under_score_func():
    pass

テストケースにて

Pythonの関数でアンダースコア始まりのものは対象外
    log to console  ${_under_score_func}

として実行した場合、

Pythonの関数でアンダースコア始まりのものは対象外    FAIL |
Variable '${_under_score_func}' not found.

となります。

 

Pythonの定数や関数のうち、除外したいものについて

今まで見てきた通り、Pythonファイルに書かれたものはRobot Frameworkの変数として使用できます。

ただ、アンダースコア始まりの関数を除き、Pythonファイルで定義されているものはRobot Frameworkの変数となってしまいます。それでは不都合があるかもしれません。

その場合、 __all__ を使うことで、Robot Frameworkの変数として扱いたいものを絞り込めます。

例えば、

__all__ = ['include_func', 'INCLUDE_VARIABLE']

INCLUDE_VARIABLE = 'foo'
EXCLUDE_VARIABLE = 'bar'


def include_func():
    pass


def exclude_func():
    pass

とします。

テストケースにて

Pythonの定数で__all__にあるものは対象
    log to console  ${INCLUDE_VARIABLE}

Pythonの定数で__all__に無いものは対象外
    log to console  ${EXCLUDE_VARIABLE}

Pythonの関数で__all__にあるものは対象
    log to console  ${include_func}

Pythonの関数で__all__に無いものは対象外
    log to console  ${exclude_func}

として実行した場合、

Pythonの定数で__all__にあるものは対象    foo
Pythonの定数で__all__にあるものは対象    | PASS |
----------------------------------------
Pythonの定数で__all__に無いものは対象外    | FAIL |
Variable '${EXCLUDE_VARIABLE}' not found. Did you mean:
    ${INCLUDE_VARIABLE}
----------------------------------------
Pythonの関数で__all__にあるものは対象    <function include_func at 0x10650d510>
Pythonの関数で__all__にあるものは対象    | PASS |
----------------------------------------
Pythonの関数で__all__に無いものは対象外    | FAIL |
Variable '${exclude_func}' not found.

となります。

 

Pythonのクラス変数・インスタンス変数を使う

Pythonのクラス変数・インスタンス変数も使えます。

ただし、

  • クラスのインタンスは使用不可
  • Pythonのクラス変数・インスタンス変数を扱うには、クラス名とクラスを定義してあるファイル名の一致が必要

です。

例えば、Pythonファイルに2つのクラスを定義します。

variable_file_class.py

class variable_file_class:
    class_val = 'python'

    def __init__(self):
        self.instance_val = 'self val'


instance_from_class = variable_file_class()


class diff_variable_file:
    diff_class_val = 'diff class'

    def __init__(self):
        self.diff_instance_val = 'self diff val'

テストケースにて

Pythonのクラスをインスタンス化して変数に設定したものは参照できない
    log to console  ${instance_from_class}

Pythonクラスのクラス変数を使う
    log to console  ${class_val}

Pythonクラスのインスタンス変数を使う
    log to console  ${instance_val}

Pythonクラスはファイル名と同じでないとクラス変数を参照できない
    log to console  ${diff_class_val}

Pythonクラスはファイル名と同じでないとインスタンス変数を参照できない
    log to console  ${diff_instance_val}

として実行した場合、

Pythonのクラスをインスタンス化して変数に設定したものは参照できない    | FAIL |
Variable '${instance_from_class}' not found.
----------------------------------
Pythonクラスのクラス変数を使う    python
Pythonクラスのクラス変数を使う    | PASS |
----------------------------------
Pythonクラスのインスタンス変数を使う    self val
Pythonクラスのインスタンス変数を使う    | PASS |
----------------------------------
Pythonクラスはファイル名と同じでないとクラス変数を参照できない     | FAIL |
Variable '${diff_class_val}' not found.
----------------------------------
Pythonクラスはファイル名と同じでないとインスタンス変数を参照できない    | FAIL |
Variable '${diff_instance_val}' not found.

となります。

 

YAMLファイルからの読み込み

変数ファイルはYAMLファイルとしても用意できます。

なお、YAMLファイルを変数ファイルとして使う場合は、PyYAMLのインストールが必要です。

pip install pyyaml

変数ファイルをYAML

yaml_dict:
    one: 1
    two: 2

と記載し、

YAMLファイルから読み込む
    log to console  ${yaml_dict}

と使った場合です。

実行結果は

YAMLファイルから読み込む    {'one': 1, 'two': 2}

です。

 

特殊な関数 get_variables() について

Robot Frameworkの変数ファイルでは、特殊な関数 get_variables() が使えます。

例えば、変数ファイルにて

def get_variables():
    return {
        'SPECIAL_FUNC': {'hoge': 'fuga'}
    }

とします。

テストケースにて

get_variablesを使う
    log to console  ${SPECIAL_FUNC}

として実行した場合、

get_variablesを使う    {'hoge': 'fuga'}

となります。

 
なお、 get_variables() 関数自体を変数として使うことはできません。

テストケースにて

get_variables自体は取れない
    log to console  ${get_variables}

として実行した場合、

get_variables自体は取れない    | FAIL |
Variable '${get_variables}' not found.

となります。

 

気になる get_variables() の挙動について

発生条件などがわかっていないので気になったというメモ書きです。

get_variables() を使った変数ファイルと、それ以外の変数ファイルを同時に読み込んだ場合、get_variables() の変数以外が

Pythonの定数    | FAIL |
Variable '${FOO}' not found.

のようになったことがありました。

復活した原因もよくわかっていません。

そのため、もし同じような事象が発生した場合は、 get_variables() を含む変数ファイルを外してみると良いかもしれません。

 

ソースコード

GitHubに上げました。 variables_samples/variable_files ディレクトリの中が今回のファイルです。
thinkAmi-sandbox/RobotFramework-sample: Robot Framewrok samples

Robot Frameworkにおける変数定義と優先順について

この記事は「Robot Framework Advent Calendar 2017 - Qiita」の9日目の記事です。

今回はRobot Frameworkで使う変数の定義方法と、変数名が重複した時の優先順についてです。

 
目次

 

環境

  • Robot Framework 3.0.2

 

Robot Frameworkの変数定義箇所

Robot Frameworkでは、いくつかの箇所で変数を定義できます。

ユーザーガイドでは以下に記載されています。

 
今回はそのうち、以下について記載します。

  • テストケースローカル
    • テストスイートやテストグローバルもあるが、今回は省略
  • 変数テーブル
  • リソースファイル
  • コマンドライン
  • 変数ファイル
    • 今回は省略

 

テストケースローカル

テストケースの中でだけ有効な変数です。

例えば、以下では変数 ${local} を定義し、値を設定しています。

ローカルで定義した変数
    Set Variable  ${local}  local_variable
    Log To Console  ${local}

実行結果です。

$ robot test_variable_priorities.robot 
...
ローカルで定義した変数    .local_variable

 

変数テーブル

テストファイル内の全テストケースで使える変数です。

以下のように定義します。

*** Variables ***
${VARIABLE_TABLE}  testcase_variable_table

 
テストケースでの使用例です。

変数テーブルで定義された変数
    Log To Console  ${VARIABLE_TABLE}

 
実行結果です。

$ robot test_variable_priorities.robot 
...
変数テーブルで定義された変数    testcase_variable_table

 

リソースファイル

リソースファイルという、外部ファイルにも変数を定義できます。

リソースファイルでは変数テーブルにて変数を定義します。

*** Variables ***
${RESOURCE}  resource

 
テストケースで利用するには、以下のように SettingsResource でリソースファイルパスを指定します。

*** Settings ***
Resource  variable_priorities_resource.robot

 
テストケースで

importしたリソースファイルで定義された変数
    Log To Console  ${RESOURCE}

とした場合の実行結果です。

$ robot test_variable_priorities.robot 
...
importしたリソースファイルで定義された変数    resource

 
なお、リソースファイルはネストすることができます。

variable_priorities_nest_resource.robot

*** Variables ***
${NEST_RESOURCE}  nest_resource_val

 
variable_priorities_resource.robot

こちらがリソースファイルを読み込んでいるリソースファイルです。

*** Settings ***
Resource  variable_priorities_nest_resource.robot

 
test_variable_priorities.robot

こちらが「リソースファイル読み込んでいるリソースファイル」を読み込んでいるテストケースです。

*** Settings ***
Resource  variable_priorities_resource.robot

*** Test Cases ***
ネストしたリソースファイルで定義された変数
    Log To Console  ${NEST_RESOURCE}

 
実行結果です。

$ robot test_variable_priorities.robot 
...
ネストしたリソースファイルで定義された変数    nest_resource_val

 

コマンドライン

コマンドラインからも、 -v オプションを使うことで変数の値を与えられます。

テストケースには、コマンドラインから渡される予定の変数名を定義しておきます。

*** Test Cases ***
コマンドラインで指定した変数
    Log To Console  ${FROM_COMMAND_LINE}

 
実行結果です。

$ robot -v FROM_COMMAND_LINE:from_command_line test_variable_priorities.robot
...
コマンドラインで指定した変数    from_command_line

 

変数の優先順

複数箇所で変数が定義されている場合、名前が重複する可能性があります。

重複した時の挙動を確認します。

 

リソースファイルとテストケースで同じ変数名を使う場合

リソースファイル

*** Variables ***
${RESOURCE}  resource

テストケース

*** Test Cases ***
リソースファイルのみの変数をこのテストケースだけで上書きした場合
    Set Test Variable  ${RESOURCE}  adohoc
    Log To Console  ${RESOURCE}

にて変数 ${RESOURCE} が重複した場合です。

実行結果は

$ robot test_variable_priorities.robot 
...
リソースファイルのみの変数をこのテストケースだけで上書きした場合    .adohoc

とテストケースの中の値が優先されます。

 

リソースのimport元と先で重複した変数

リソースファイルとネストしたリソースファイルで変数名が重複した場合です。

ネストしたリソースファイル

*** Variables ***
${RESOURCE_IMPORT}  nest_resource_import

リソースファイル

*** Settings ***
Resource  variable_priorities_nest_resource.robot

*** Variables ***
${RESOURCE_IMPORT}  resource_import

にて変数 ${RESOURCE_IMPORT} が重複していた場合です。

テストケースを

*** Test Cases ***
リソースファイルのimport元と先で重複した変数
    Log To Console  ${RESOURCE_IMPORT}

として実行すると

リソースファイルのimport元と先で重複した変数    resource_import

と、最初に読み込まれたリソースファイルの変数の値となります。

 

リソースファイルとテストケースの変数テーブルで重複した変数

リソースファイル

*** Variables ***
${VARIABLE_TABLE}  resource_variable_table

テストケースの変数テーブル

*** Variables ***
${VARIABLE_TABLE}  testcase_variable_table

*** Test Cases ***
変数テーブルとリソースファイルで重複した変数
    Log To Console  ${VARIABLE_TABLE}

で変数 ${VARIABLE_TABLE} が重複していた場合です。

実行結果は

変数テーブルとリソースファイルで重複した変数    testcase_variable_table

と、テストケースの変数テーブルが優先されます。

 

リソースファイルとテストケースの変数テーブルとコマンドラインで重複した変数

リソースファイル

*** Variables ***
${COMMAND}  resource_command

テストケースファイルの変数テーブル

*** Settings ***
Resource  variable_priorities_resource.robot

*** Variables ***
${COMMAND}  testcase_command


*** Test Cases ***
コマンドラインと変数テーブルとリソースファイルで重複した変数
    Log To Console  ${COMMAND}

コマンドライン

$ robot -v COMMAND:command_line test_variable_priorities.robot 

で変数 ${COMMAND} が重複していた場合です。

実行結果は

$ robot -v COMMAND:command_line test_variable_priorities.robot 
...
コマンドラインと変数テーブルとリソースファイルで重複した変数    command_line

と、コマンドラインが優先されます。

 

ソースコード

GitHubに上げました。 variables_samples/priorities ディレクトリの中が今回のファイルです。
thinkAmi-sandbox/RobotFramework-sample: Robot Framewrok samples

Robot Frameworkを実行後に出力されるファイルについて

この記事は「Robot Framework Advent Calendar 2017 - Qiita」の8日目の記事です。

Robot Frameworkのデフォルト設定では、テストの実行後にログファイルやレポートファイルが自動生成されます。

ログファイル

f:id:thinkAmi:20171207225448p:plain

もしテストが失敗した場合、その詳細情報がログファイルに出力されます。

f:id:thinkAmi:20171207225541p:plain

 
レポートファイル(すべてのテストがパスした時)

f:id:thinkAmi:20171207225511p:plain

 
レポートファイル(いずれかのテストが失敗した時)

f:id:thinkAmi:20171207225527p:plain

 
また、自動生成されるファイル名のデフォルト名称は

  • log.html
    • ログファイル
  • report.html
    • レポートファイル
  • output.xml
    • ログXMLファイル
    • ログ、レポート等のファイルの元となるファイル

です。

デフォルト設定では、これらのファイルはテストを実行した時のカレントディレクトリに出力されます。

 
また、自動生成されるファイル以外にも、

  • xUnitと互換性のあるファイル
  • デバッグファイル

も追加で出力できます。

そこで今回は、それらのファイル出力を試してみます。

 
目次

 

環境

  • Python 3.6.3
  • Robot Framework 3.0.2

 

テストコード中でファイル名を変更 (不可)

レポートファイル名は、自動変数 ${REPORT FILE} に設定されています。

 
そこで、試しに ${REPORT FILE} を変更してみます。

*** Variables ***
# Variablesにてセット
${REPORT FILE}  rename_report_in_variables.html

*** TestCases ***

レポートファイル名を変更する
    # 見やすいように改行する
    Log To Console  ${EMPTY}

    # 変数としてセット
    Set Variable  ${REPORT FILE}  rename_report_in_test_cases1.html
    Log To Console  ${REPORT FILE}

    # グローバルな変数にセット
    Set Global Variable  ${REPORT FILE}  rename_report_in_test_cases2.html
    Log To Console  ${REPORT FILE}

実行結果です。

$ robot rename.robot 
==========================
Rename
==========================
レポートファイル名を変更する
../path/to/report.html
..rename_report_in_test_cases2.html
レポートファイル名を変更する    | PASS |
------------------------------------
Rename    | PASS |
1 critical test, 1 passed, 0 failed
1 test total, 1 passed, 0 failed
==========================
Output:  /path/to/output.xml
Log:     /path/to/log.html
Report:  /path/to/report.html

キーワード Set Global Variable では値の書き換えはできたものの、最終的なログファイル名は変わりませんでした。

 

コマンドラインオプションを使う

ファイル名はコマンドラインオプションから変更できます。

ヘルプに記載がありました。

$ robot --help
...
 -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`
                          similarly as --log. Default: report.html

 
試してみます。

$ robot --log re_log.html --report re_report.html --output re_output.xml rename.robot 
===============
Rename
===============
...
Output:  /path/to/re_output.xml
Log:     /path/to/re_log.html
Report:  /path/to/re_report.html

 
各ファイル名が変更されました。

 
ちなみに、Robot Frameworkのコマンドラインオプションは、いずれもテストファイルよりも前に付ける必要があります。

上記例の場合、ファイル rename.robot よりも前に書きます。書かない場合、

[ ERROR ] Parsing '--output' failed: Data source does not exist.

というエラーが出ます。

 

出力ファイルがいらない場合

なお、出力ファイルがいらない場合は、それぞれのコマンドラインオプションに None を設定します。

$ robot --log None --report None --output None rename.robot
...
Output:  None

 

xUnitのログと互換性のあるファイルが欲しい場合

コマンドラインオプション --xunit (-x) を使います。
http://robotframework.org/robotframework/latest/RobotFrameworkUserGuide.html#xunit-compatible-result-file

$ robot --log None --report None --output None --xunit xunit_report.xml rename.robot
...
Output:  None
XUnit:   /path/to/xunit_report.xml

結果です。

<?xml version="1.0" encoding="UTF-8"?>
<testsuite name="Rename" tests="1" errors="0" failures="1" skip="0">
<testcase classname="Rename" name="レポートファイル名を変更する" time="0">
<failure message="AssertionError" type="AssertionError"></failure>
</testcase>
</testsuite>

 

デバッグファイルが欲しい場合

コマンドラインオプション --debugfile (-b) を使います。
http://robotframework.org/robotframework/latest/RobotFrameworkUserGuide.html#debug-file

$ robot --log None --report None --output None --debugfile debug.txt rename.robot
...
Debug:   /path/to/debug.txt
Output:  None

デバッグ内容がプレーンテキストとして作成されます。

中身はこんな感じです。

==============================================================================
20171207 23:14:38.725 - INFO - + START SUITE: Rename [ ]
==============================================================================
20171207 23:14:38.725 - INFO - +- START TEST: レポートファイル名を変更する [ ]
------------------------------------------------------------------------------
20171207 23:14:38.727 - INFO - +-- START KW: BuiltIn.Log To Console [ ${EMPTY} ]
20171207 23:14:38.727 - INFO - +-- END KW: BuiltIn.Log To Console (0)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
20171207 23:14:38.728 - INFO - +-- START KW: BuiltIn.Set Variable [ ${REPORT FILE} | rename_report_in_test_cases1.html ]
20171207 23:14:38.728 - INFO - +-- END KW: BuiltIn.Set Variable (1)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
20171207 23:14:38.728 - INFO - +-- START KW: BuiltIn.Log To Console [ ${REPORT FILE} ]
20171207 23:14:38.728 - INFO - +-- END KW: BuiltIn.Log To Console (0)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
20171207 23:14:38.729 - INFO - +-- START KW: BuiltIn.Set Global Variable [ ${REPORT FILE} | rename_report_in_test_cases2.html ]
20171207 23:14:38.729 - INFO - ${REPORT FILE} = rename_report_in_test_cases2.html
20171207 23:14:38.729 - INFO - +-- END KW: BuiltIn.Set Global Variable (1)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
20171207 23:14:38.729 - INFO - +-- START KW: BuiltIn.Log To Console [ ${REPORT FILE} ]
20171207 23:14:38.729 - INFO - +-- END KW: BuiltIn.Log To Console (0)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
20171207 23:14:38.730 - INFO - +-- START KW: BuiltIn.Fail [ ]
20171207 23:14:38.730 - FAIL - AssertionError
20171207 23:14:38.730 - DEBUG - Traceback (most recent call last):
  None
20171207 23:14:38.730 - INFO - +-- END KW: BuiltIn.Fail (0)
------------------------------------------------------------------------------
20171207 23:14:38.730 - INFO - +- END TEST: レポートファイル名を変更する (5)
------------------------------------------------------------------------------
20171207 23:14:38.731 - INFO - + END SUITE: Rename (43)
==============================================================================

 

ファイルにタイムスタンプが欲しい場合

コマンドラインオプション --timestampoutputs (-T) を使います。

$ robot --debugfile debug.txt --xunit xunit.xml --timestampoutputs rename.robot
...
Debug:   /path/to/debug-20171207-231818.txt
Output:  /path/to/output-20171207-231818.xml
XUnit:   /path/to/xunit-20171207-231818.xml
Log:     /path/to/log-20171207-231818.html
Report:  /path/to/report-20171207-231818.html

 
出力ファイルに関しては、他にも公式ドキュメントに書いてありますので、一度目を通しておくと良いかと思います。
3.5.1 Different output files - Robot Framework User Guide

Robot Frameworkのライブラリを自作する

この記事は「Robot Framework Advent Calendar 2017 - Qiita」の7日目の記事です。

Robot Frameworkを使っている中で、Robot Frameworkのライブラリを自作したいことがあるかもしれません。

ユーザーガイドにて方法を調べてみると、以下に記載がありました。
4.1 Creating test libraries - Robot Framework User Guide

 
そこで今回は、ユーザーガイドに従ってライブラリを自作してみます。

 
目次

 

環境

  • Robot Framework 3.0.2
  • Python 3.6.3

 

ライブラリの作成

ユーザーガイドによると、ライブラリはPythonJava、どちらでも作成できるようです。今回はPythonで作成してみます。

また、今回はターミナルにログを出力するライブラリを作ります。

 
Robot Frameworkの Programmatic logging APIs を使うことで、ターミナルにログが出力できるようです。
Programmatic logging APIs - Robot Framework User Guide

 
今回は、

  • logging APIのモジュール robot.api.logger を使用
  • Robot Frameworkのテストで使うためのキーワードは、英語と日本語の両方を用意
  • ライブラリ名は MyLibrary.py
    • PascalCaseで書く慣習のようですが、小文字だけでも問題ない
    • MyLibraryでもmy_libraryでも動作

とします。

MyLibrary.py

from robot.api import logger

def hello_world(key='default'):
    logger.console(f'{key} de hello world')

def ハロー_ワールド(key='デフォルト'):
    logger.console(f'{key} を使ったハローワールド')

 
完成したライブラリをRobot Frameworkで使うためには、PYTHONPATH など module search path と呼ばれる所にライブラリを置く必要があります。
3.4.5 Configuring where to search libraries and other extensions - Robot Framework User Guide

 
その場所に

  • 自作ライブラリファイルをそのまま
  • setuptoolsなどを使ってパッケージング

のいずれかで置けば良いようです。
Packaging libraries - Robot Framework User Guide

 
今回は、自作ライブラリをそのまま置くことにします。

 

ライブラリを使用するテストファイルを用意

自作したライブラリはSettingsで指定します。

なお、今回のテストファイルでは、ライブラリで定義したキーワードはどの程度まで認識されるかを調べるため、キーワードの区切り文字として

  • スペースなし
  • アンダースコア
  • 半角スペース
  • 全角スペース1つ
  • 全角スペース複数
  • タブ文字

をそれぞれ試してみます。

*** Settings ***
Library  MyLibrary


*** Test Cases ***
英語のキーワードをテストする
    # 見やすいように改行する
    Log To Console  ${EMPTY}

    # キーワード、引数の順(キーワードと引数の間は半角スペース2個空けている)
    hello_world  アンダースコア
    hello world  半角スペース
    helloworld  スペースなし


日本語のキーワードをテストする
    # 見やすいように改行する
    Log To Console  ${EMPTY}

    # キーワード、引数の順(キーワードと引数の間は半角スペース2個空けている)
    ハロー_ワールド  アンダースコア
    ハロー ワールド  半角スペース
    ハローワールド  スペースなし
    ハロー ワールド  全角スペース1個
    ハロー  ワールド  全角スペース2個
    ハロー   ワールド  タブ文字

 

実行

ファイルの配置

現在のファイルの配置は以下の通りです。

自作ライブラリとテストファイルを同じディレクトリに入れてあります。

$ pwd 
/path/to/create_library_sample

$ tree -L 1
.
├── MyLibrary.py
└── test_hello_using_my_library.robot

 

実行コマンド
robotコマンド

普通に robot コマンドで実行した場合、

$ robot test_hello_using_my_library.robot 
[ ERROR ] Error in file '/path/to/test_hello_using_my_library.robot': Importing test library 'MyLibrary' failed: ModuleNotFoundError: No module named 'MyLibrary'
Traceback (most recent call last):
  None
PYTHONPATH:
  /path/to/venv/bin
  /path/to/.pyenv/versions/3.6.3/lib/python36.zip
  /path/to/.pyenv/versions/3.6.3/lib/python3.6
  /path/to/.pyenv/versions/3.6.3/lib/python3.6/lib-dynload
  /path/to/venv/lib/python3.6/site-packages
==========================
Test Hello Using My Library
==========================
英語のキーワードをテストする
英語のキーワードをテストする    | FAIL |
No keyword with name 'hello_world' found.
------------------------------------
日本語のキーワードをテストする
日本語のキーワードをテストする    | FAIL |
No keyword with name 'ハロー_ワールド' found.
------------------------------------
Test Hello Using My Library    | FAIL |
2 critical tests, 0 passed, 2 failed
2 tests total, 0 passed, 2 failed
==========================

と、キーワードが見つからないというエラーになります。

PYTHONPATHなどで自作ライブラリが見つからないためです。

 

robotコマンド + --pythonpath (-P) オプション

Robot Frameworkの実行コマンド robot には、指定したパスをmodule search pathに追加してくれる --pythonpath (-P) オプションがあります。

試してみます。

$ robot -P . test_hello_using_my_library.robot 
===============================
Test Hello Using My Library
===============================
英語のキーワードをテストする
.アンダースコア de hello world
.半角スペース de hello world
.スペースなし de hello world
英語のキーワードをテストする    | PASS |
-------------------------------------------
日本語のキーワードをテストする
.アンダースコア を使ったハローワールド
.半角スペース を使ったハローワールド
.スペースなし を使ったハローワールド
.全角スペース1個 を使ったハローワールド
.全角スペース2個 を使ったハローワールド
日本語のキーワードをテストする    | FAIL |
No keyword with name 'ハロー' found.
-------------------------------------------
Test Hello Using My Library    | FAIL |
2 critical tests, 1 passed, 1 failed
2 tests total, 1 passed, 1 failed
===============================

自作ライブラリを認識してくれたようです。

ただ、キーワードが一つ失敗しています。タブ文字のキーワード指定っぽいです。そのため、

日本語のキーワードをテストする
#...
    #ハロー  ワールド  タブ文字

コメントアウトして再実行してみます。

$ robot -P . test_hello_using_my_library.robot 
===============================
Test Hello Using My Library
===============================
英語のキーワードをテストする
.アンダースコア de hello world
.半角スペース de hello world
.スペースなし de hello world
英語のキーワードをテストする    | PASS |
-------------------------------------------
日本語のキーワードをテストする
.アンダースコア を使ったハローワールド
.半角スペース を使ったハローワールド
.スペースなし を使ったハローワールド
.全角スペース1個 を使ったハローワールド
.全角スペース2個 を使ったハローワールド
日本語のキーワードをテストする    | PASS |
-------------------------------------------
Test Hello Using My Library    | PASS |
2 critical tests, 2 passed, 0 failed
2 tests total, 2 passed, 0 failed
===============================

テストをパスしました。

 

python -m robot で実行

Robot Frameworkは、Python-m コマンドラインオプションでも実行できます。

 
Python-m コマンドラインオプションは、

このオプションが指定された場合、 sys.argv の最初の要素はモジュールファイルのフルパスになります (モジュールファイルを検索している間、最初の要素は "-m" に設定されます)。 -c オプションと同様に、カレントディレクトリが sys.path の先頭に追加されます。

-m <module-name> - 1. コマンドラインと環境 — Python 3.6.3 ドキュメント

です。

そのため、テストファイルと自作ライブラリのあるディレクトリに移動してからテストを実行することで、自作ライブラリを認識します。

# ディレクトリへ移動
$ cd /path/to/create_library_sample

# ディレクトリの中身を確認
create_library_sample $ tree -L 1
.
├── MyLibrary.py
└── test_hello_using_my_library.robot

# -m オプションを付けて実行
$ python -m robot test_hello_using_my_library.robot 
=========================
Test Hello Using My Library
=========================
英語のキーワードをテストする
.アンダースコア de hello world
.半角スペース de hello world
.スペースなし de hello world
英語のキーワードをテストする    | PASS |
-----------------------------------
日本語のキーワードをテストする
.アンダースコア を使ったハローワールド
.半角スペース を使ったハローワールド
.スペースなし を使ったハローワールド
.全角スペース1個 を使ったハローワールド
.全角スペース2個 を使ったハローワールド
日本語のキーワードをテストする    | PASS |
-----------------------------------
Test Hello Using My Library    | PASS |
2 critical tests, 2 passed, 0 failed
2 tests total, 2 passed, 0 failed
=========================

 

ソースコード

GitHubに上げました。create_library_sample ディレクトリが今回のものです。
thinkAmi-sandbox/RobotFramework-sample: Robot Framewrok samples

Robot Framework + SeleniumLibraryで、Headless Firefoxを動かす

この記事は「Robot Framework Advent Calendar 2017 - Qiita」の6日目の記事です。

昨日はRobot Framework + SeleniumLibraryで Headless Chromeを動かしました。
Robot Framework + SeleniumLibrary + Selenium3.8以降でHeadless Chromeを動かす - メモ的な思考的な

 
そんな中、FirefoxでもHeadlessが実装されたと聞きました。LinuxはFirefox55から、Mac/WindowsはFirefox56から動作するようです。
ヘッドレスモード - Mozilla | MDN

 
そこで今回、Robot Framework + SeleniumLibraryで Headless Firefoxを動かしてみます。

 
目次

 

環境

 

HeadlessなFirefoxを起動するには

MDNのドキュメントに従い、

${binary} =  Evaluate  sys.modules['selenium.webdriver.firefox.firefox_binary'].FirefoxBinary()  sys
Call Method  ${binary}  add_command_line_options  -headless
Create Webdriver  Firefox  firefox_binary=${binary}

と実装してみましたが、非HeadlessなFirefoxが起動しました。

 
仕方ないので他の方法を探してみたところ、以下のページに FirefoxOptions を使う方法が記載されていました。
selenium - Running headless Firefox WebDriver on Jenkins (Windows OS) - Stack Overflow

そのため、

${options} =  Evaluate  sys.modules['selenium.webdriver.firefox.options'].Options()  sys
Call Method  ${options}  add_argument  -headless
Create Webdriver  Firefox  firefox_options=${options}

としたところ、HeadlessなFirefoxが起動しました。

 
さらに、selenium 3.8.0より、Firefoxのoptions.pyにも set_headless() メソッドが追加されていました。

 
そのため、selenium 3.8.0からは、以下の方法でもHeadless Firefoxを起動できます。

${options} =  Evaluate  sys.modules['selenium.webdriver.firefox.options'].Options()  sys
Call Method  ${options}  set_headless
Create Webdriver  Firefox  firefox_options=${options}

 

Headless Firefoxを試してみる

Headless Chromeと同様、Headless Firefoxを使って、GooglePythonを検索してスクリーンショットを撮ってみます。

*** Settings ***
Library  SeleniumLibrary


*** Keywords ***
set_headlessメソッドがない場合はテストをパスする
    ${version} =  Evaluate  selenium.__version__  selenium
    ${selenium_version} =  Evaluate  importlib.import_module('distutils.version').LooseVersion($version)  importlib
    # set_headlessメソッドは、python seleniumの3.8.0以降に実装された
    ${min_version} =  Evaluate  importlib.import_module('distutils.version').LooseVersion('3.8.0')  importlib

    Pass Execution If  $selenium_version < $min_version  seleniumが${min_version}以上でないと動作しません


set_headlessメソッドを使ってHeadlessなFirefoxを起動する
    set_headlessメソッドがない場合はテストをパスする
    ${options} =  Evaluate  sys.modules['selenium.webdriver.firefox.options'].Options()  sys
    Call Method  ${options}  set_headless
    Create Webdriver  Firefox  firefox_options=${options}


add_argumentメソッドを使ってHeadlessなFirefoxを起動する
     ${options} =  Evaluate  sys.modules['selenium.webdriver.firefox.options'].Options()  sys
     Call Method  ${options}  add_argument  -headless
     Create Webdriver  Firefox  firefox_options=${options}


GoogleでPythonを検索してスクリーンショットを撮り、結果を出力する
    # Googleのトップ画面を開く
    Go To  https://www.google.co.jp/

    # タイトルにGoogleが含まれていることを確認する
    ${page_title} =  Get Title
    Should Contain  ${page_title}  Google

    # 検索後を入力して送信する
    Input Text  name=q  Python
    Press Key  name=q  \\13

    # Ajax遷移のため、適当に2秒待つ
    Sleep  2sec

    # タイトルにPythonが含まれていることを確認する
    ${result_title} =  Get Title
    Should Contain  ${result_title}  Python

    # スクリーンショットを撮る
    Capture Page Screenshot  filename=result_google_python.png

    # ログを見やすくするために改行を入れる
    Log To Console  ${SPACE}

    # 検索結果を表示する
    @{web_elements} =  Get Webelements  css=h3 > a
    :For  ${web_element}  In  @{web_elements}
    \  ${text} =  Get Text  ${web_element}
    \  Log To Console  ${text}
    \  ${href} =  Call Method  ${web_element}  get_attribute  href
    \  Log To Console  ${href}

    # ブラウザを終了する
    Close Browser


*** TestCases ***
add_argumentメソッドを使ってHeadlessなFirefoxを起動しテストする
    add_argumentメソッドを使ってHeadlessなFirefoxを起動する
    GoogleでPythonを検索してスクリーンショットを撮り、結果を出力する

set_headlessメソッドを使ってHeadlessなFirefoxを起動しテストする
    set_headlessメソッドを使ってHeadlessなFirefoxを起動する
    GoogleでPythonを検索してスクリーンショットを撮り、結果を出力する

 

実行結果

実行ログ

両方ともテストをパスしました。

$ robot test_google_with_headless_firefox.robot 
=============================
Test Google With Headless Firefox
=============================
add_argumentメソッドを使ってHeadlessなFirefoxを起動しテストする       . 
Python - ウィキペディア
https://ja.wikipedia.org/wiki/Python
Pythonとは - python.jp
https://www.python.jp/about/
専門知識いらず!Pythonとは?言語の特徴から網羅的に徹底解説 | 侍 ...
https://www.sejuku.net/blog/7720
Python基礎講座(1 Pythonとは) - Qiita
https://qiita.com/Usek/items/ff4d87745dfc5d9b85a4
Python 13370 posts - Qiita
https://qiita.com/tags/Python
Python入門
http://www.tohoho-web.com/python/
Python | プログラミングの入門なら基礎から学べるProgate[プロゲート]
https://prog-8.com/languages/python
Python 3を使うべきでない場合(なんてない) | プログラミング | POSTD
http://postd.cc/case-python-3/
Pythonとは?何に使えるの?Pythonの特徴や使い道を…|Udemy メディア
https://udemy.benesse.co.jp/development/python.html
Pythonは今のうちに習得すべき?『スラスラわかるPython』著者・岩崎さんと ...
https://codezine.jp/article/detail/10329
add_argumentメソッドを使ってHeadlessなFirefoxを起動しテストする       | PASS |
----------------------------------------
set_headlessメソッドを使ってHeadlessなFirefoxを起動しテストする       . 
Python - ウィキペディア
https://ja.wikipedia.org/wiki/Python
Pythonとは - python.jp
https://www.python.jp/about/
専門知識いらず!Pythonとは?言語の特徴から網羅的に徹底解説 | 侍 ...
https://www.sejuku.net/blog/7720
Python基礎講座(1 Pythonとは) - Qiita
https://qiita.com/Usek/items/ff4d87745dfc5d9b85a4
Python 13370 posts - Qiita
https://qiita.com/tags/Python
Python入門
http://www.tohoho-web.com/python/
Python | プログラミングの入門なら基礎から学べるProgate[プロゲート]
https://prog-8.com/languages/python
Python 3を使うべきでない場合(なんてない) | プログラミング | POSTD
http://postd.cc/case-python-3/
Pythonとは?何に使えるの?Pythonの特徴や使い道を…|Udemy メディア
https://udemy.benesse.co.jp/development/python.html
Pythonは今のうちに習得すべき?『スラスラわかるPython』著者・岩崎さんと ...
https://codezine.jp/article/detail/10329
set_headlessメソッドを使ってHeadlessなFirefoxを起動しテストする       | PASS |
----------------------------------------
Test Google With Headless Firefox       | PASS |
2 critical tests, 2 passed, 0 failed
2 tests total, 2 passed, 0 failed
=============================

 

スクリーンショット

Headless Firefoxですが、問題なくスクリーンショットが撮れています。

f:id:thinkAmi:20171205211805p:plain

 
昨日のChromeと比べて撮影されている範囲が広くなっています。スクリーンショットはブラウザにより違いますね。

 

ソースコード

GitHubに上げました。 selenium_firefox_headless_sample ディレクトリの test_google_with_headless_firefox.robot ファイルが今回のものです。
thinkAmi-sandbox/RobotFramework-sample: Robot Framewrok samples

Robot Framework + SeleniumLibrary + Selenium3.8以降でHeadless Chromeを動かす

この記事は「Robot Framework Advent Calendar 2017 - Qiita」の5日目の記事です。

 
以前、 Selenium2Library 時代にHeadless Chromeを使ってみました。
Robot FrameworkでHeadless Chromeを使ってみた - メモ的な思考的な

 
その後、

  • SeleniumLibrary にライブラリ名が変わった
  • Seleniumのバージョンが上がって、便利なメソッドができていた

となったため、改めて Robot Framework + SeleniumLibraryで Headless Chromeを動かしてみます。

 
目次

 

環境

  • Python 3.6.3
  • Chrome 62.0.3202.94
  • chromedriver 2.33
  • RobotFramework 3.0.2
  • SeleniumLibrary 3.0.0
  • selenium 3.8.0

 

set_headless() メソッドを使う

Selenium 3.8より、 selenium.webdriver.chrome.options.pyset_selenium() メソッドが追加されていました。
https://github.com/SeleniumHQ/selenium/blob/selenium-3.8.0/py/selenium/webdriver/chrome/options.py#L161

ソースコードを読むと、ChromeOptiosにheadlessを設定してくれるようなので、今回はこれを使ってみます。

 

実装について

Headless Chromeを set_headless() メソッドを使って起動する

Headless Chromeset_headless() メソッドを使って起動するには、add_argment()メソッドと同じくChromeOptionsクラスを使い、

を行います。

# ChromeOptionsクラスをインスタンス化
${options} =  evaluate  sys.modules['selenium.webdriver'].ChromeOptions()  sys

# ChromeOptionsインスタンスの set_headless メソッドを実行
call method  ${options}  set_headless

create webdriver  Chrome  chrome_options=${options}

 

全体

add_argment() と set_headless() の両パターンを書いてみました。

*** Settings ***
Library  SeleniumLibrary


*** Keywords ***
set_headlessメソッドがない場合はテストをパスする
    ${version} =  evaluate  selenium.__version__  selenium
    ${selenium_version} =  evaluate  importlib.import_module('distutils.version').LooseVersion($version)  importlib
    # set_headlessメソッドは、python seleniumの3.8.0以降に実装された
    ${min_version} =  evaluate  importlib.import_module('distutils.version').LooseVersion('3.8.0')  importlib

    Pass Execution If  $selenium_version < $min_version  seleniumが${min_version}以上でないと動作しません


set_headlessメソッドを使ってHeadlessなChromeを起動する
    set_headlessメソッドがない場合はテストをパスする
    ${options} =  evaluate  sys.modules['selenium.webdriver'].ChromeOptions()  sys
    Call Method  ${options}  set_headless
    Create Webdriver  Chrome  chrome_options=${options}


add_argumentメソッドを使ってHeadlessなChromeを起動する
    # https://groups.google.com/d/msg/robotframework-users/gPsiVaMo19A/cBRH7mr2BAAJ
    ${options} =  evaluate  sys.modules['selenium.webdriver'].ChromeOptions()  sys
    Call Method  ${options}  add_argument  --headless
    Create Webdriver  Chrome  chrome_options=${options}


GoogleでPythonを検索してスクリーンショットを撮り、結果を出力する
    # 以下のコードをRobot Framework風にした
    # http://qiita.com/orangain/items/db4594113c04e8801aad

    # Googleのトップ画面を開く
    Go To  https://www.google.co.jp/

    # タイトルにGoogleが含まれていることを確認する
    ${page_title} =  get title
    Should Contain  ${page_title}  Google

    # 検索後を入力して送信する
    Input Text  name=q  Python
    # Robot FrameworkではEnterキーは\\13になる
    # https://github.com/robotframework/Selenium2Library/issues/4
    Press Key  name=q  \\13

    # Ajax遷移のため、適当に2秒待つ
    Sleep  2sec

    # タイトルにPythonが含まれていることを確認する
    ${result_title} =  get title
    should contain  ${result_title}  Python

    # スクリーンショットを撮る
    Capture Page Screenshot  filename=result_google_python2.png

    # ログを見やすくするために改行を入れる
    Log To Console  ${SPACE}

    # 検索結果を表示する
    # ForでElementを回したかったことから、WebElementを取得し、そのAPIを利用する
    # http://robotframework.org/Selenium2Library/Selenium2Library.html#Get%20Webelements
    # https://stackoverflow.com/a/42508200
    @{web_elements} =  Get Webelements  css=h3 > a
    :For  ${web_element}  In  @{web_elements}
    \  ${text} =  Get Text  ${web_element}
    \  Log To Console  ${text}
    # 以下を参考に、WebElementからattribute(href)を取得
    # https://groups.google.com/d/msg/robotframework-users/xx3KYxpDu_w/0hyulqKPKQAJ
    # http://seleniumhq.github.io/selenium/docs/api/py/webdriver_remote/selenium.webdriver.remote.webelement.html#selenium.webdriver.remote.webelement.WebElement.get_attribute
    \  ${href} =  Call Method  ${web_element}  get_attribute  href
    \  Log To Console  ${href}

    # ブラウザを終了する
    Close Browser


*** TestCases ***
add_argumentメソッドを使ってHeadlessなChromeを起動しテストする
    add_argumentメソッドを使ってHeadlessなChromeを起動する
    GoogleでPythonを検索してスクリーンショットを撮り、結果を出力する

set_headlessメソッドを使ってHeadlessなChromeを起動しテストする
    set_headlessメソッドを使ってHeadlessなChromeを起動する
    GoogleでPythonを検索してスクリーンショットを撮り、結果を出力する

 

実行結果

実行ログ

両方ともテストをパスしました。

$ robot test_google_with_headless_chrome.robot 
==============================
Test Google With Headless Chrome
==============================
add_argumentメソッドを使ってHeadlessなChromeを起動しテストする        . 
Python - ウィキペディア
https://ja.wikipedia.org/wiki/Python
Pythonとは - python.jp
https://www.python.jp/about/
専門知識いらず!Pythonとは?言語の特徴から網羅的に徹底解説 | 侍 ...
https://www.sejuku.net/blog/7720
Python基礎講座(1 Pythonとは) - Qiita
https://qiita.com/Usek/items/ff4d87745dfc5d9b85a4
Python 13370 posts - Qiita
https://qiita.com/tags/Python
Python入門
http://www.tohoho-web.com/python/
Python | プログラミングの入門なら基礎から学べるProgate[プロゲート]
https://prog-8.com/languages/python
Pythonとは?何に使えるの?Pythonの特徴や使い道を…|Udemy メディア
https://udemy.benesse.co.jp/development/python.html
Python 3を使うべきでない場合(なんてない) | プログラミング | POSTD
http://postd.cc/case-python-3/
Pythonは今のうちに習得すべき?『スラスラわかるPython』著者・岩崎さんと ...
https://codezine.jp/article/detail/10329
add_argumentメソッドを使ってHeadlessなChromeを起動しテストする        | PASS |
-----------------------------------------
set_headlessメソッドを使ってHeadlessなChromeを起動しテストする        . 
Python - ウィキペディア
https://ja.wikipedia.org/wiki/Python
Pythonとは - python.jp
https://www.python.jp/about/
専門知識いらず!Pythonとは?言語の特徴から網羅的に徹底解説 | 侍 ...
https://www.sejuku.net/blog/7720
Python基礎講座(1 Pythonとは) - Qiita
https://qiita.com/Usek/items/ff4d87745dfc5d9b85a4
Python 13370 posts - Qiita
https://qiita.com/tags/Python
Python入門
http://www.tohoho-web.com/python/
Python | プログラミングの入門なら基礎から学べるProgate[プロゲート]
https://prog-8.com/languages/python
Pythonとは?何に使えるの?Pythonの特徴や使い道を…|Udemy メディア
https://udemy.benesse.co.jp/development/python.html
Python 3を使うべきでない場合(なんてない) | プログラミング | POSTD
http://postd.cc/case-python-3/
Pythonは今のうちに習得すべき?『スラスラわかるPython』著者・岩崎さんと ...
https://codezine.jp/article/detail/10329
set_headlessメソッドを使ってHeadlessなChromeを起動しテストする        | PASS |
-----------------------------------------
Test Google With Headless Chrome        | PASS |
2 critical tests, 2 passed, 0 failed
2 tests total, 2 passed, 0 failed
==============================

 

スクリーンショット

Headless Chromeですが、問題なくスクリーンショットが撮れています。

f:id:thinkAmi:20171205210839p:plain

 

ソースコード

GitHubに上げました。 selenium_chrome_headless_sample ディレクトリの test_google_with_headless_chrome.robot ファイルが今回のものです。
thinkAmi-sandbox/RobotFramework-sample: Robot Framewrok samples