Python + pytestにて、pytestに独自のコマンドラインオプションを追加する

Python + pytestにて、コマンドラインオプションを追加して、コマンドラインから値を受け取った時のメモを残します。

 
目次

 

環境

 

pytestのコマンドラインオプションの追加方法

公式ドキュメントに情報がありました。
Basic patterns and examples — pytest documentation

とすれば良いようです。

 

conftest.pyの実装

公式ドキュメントによると、コマンドラインオプションを実装するための引数は標準モジュールの argparse と似ていました。

 
そこで今回は、

の2つを実装してみます。

まずは、pytest_addoption()関数に、追加するオプションの内容を記述します。 action='store'なものが前者、action='store_true'なものが後者となります。

def pytest_addoption(parser):
    """add commandline options"""
    parser.addoption('--fruit', action='store', default='ham',
                     help='fruit name: apple, grape, banana, etc')
    parser.addoption('--season', action='store_true',
                     help='fruit season now')

 
続いて、コマンドラインオプションから渡された値を返す、@pytest.fixtureデコレータの付いた関数を用意します。

request.config.getoption()メソッドの引数に、コマンドラインオプション名(parser.addoption()の第一引数と同じ名前)を指定します。

@pytest.fixture
def favorite_fruit(request):
    return request.config.getoption('--fruit')


@pytest.fixture
def is_season(request):
    return request.config.getoption('--season')

 

テストコードの実装

テストコードの引数に、conftext.pyで指定したfixtureデコレータのある関数の名前を指定します。

favorite_fruitis_seasonが該当します。

def test_fruit(favorite_fruit, is_season):
    print(f'\nfruit:{favorite_fruit}, is_season:{is_season}')
    assert True

 

テストの実行

ヘルプを見ると、オプションが追加されていました。

$ python -m pytest e.g._add_commandline_option/ --help
...
custom options:
  --fruit=FRUIT         fruit name: apple, grape, banana, etc
  --season              fruit season now
...

 
実行してみます。

なお、テストをパスした時はprint()の結果が出力されないため、 -sオプションを付けて実行します。

# 独自オプション無し:fruit・is_seasonともデフォルト値
$ python -m pytest e.g._add_commandline_option/ -s
...
fruit:ham, is_season:False

# fruitオプションあり:渡したbananaが表示
$ python -m pytest e.g._add_commandline_option/ -s --fruit banana
...
fruit:banana, is_season:False

# seasonオプションあり:is_seasonがTrueになった
$ python -m pytest e.g._add_commandline_option/ -s --fruit banana --season
...
fruit:banana, is_season:True

テストコードに、コマンドラインオプションの値が引き渡されていました。

 

応用:コマンドラインオプションで指定したテストコード以外はスキップする

pytestでは

  • pytest.mark.skipでテストをスキップ
  • pytest.mark.skipifで、条件に一致した場合にテストをスキップ

などの制御ができます。

ただ、上記の方法では、「コマンドラインオプションで指定したテストコード以外はスキップする」を実現できませんでした。コマンドラインオプションの値をマーカーに渡すことができなかったためです。

そこで公式ドキュメントを見たところ、

を組み合わせれば良さそうでした。
Working with custom markers — pytest documentation

独自コマンドラインオプションを追加したときと同様、conftest.pyとテストコードに実装します。

 

conftest.pyの実装

conftest.pyには

  • pytest_addoption()関数にて、独自コマンドラインオプションを追加 (今回は、targetオプション)
  • pytest_configure()関数にて、独自マーカーを追加 (今回は、pytest.mark.test_number)
  • @pytest.fixtureデコレータの付いた関数にて、独自コマンドラインオプションの値を取得
  • pytest_runtest_setup()関数にて、スキップするかどうかを判定

の4つを実装しました。

 

def pytest_addoption(parser):
    """add commandline options"""
    parser.addoption('--target', action='store',
                     help='if commandline args match test decorator, run test. if not, skip it')


def pytest_configure(config):
    """add custom marker"""
    config.addinivalue_line('markers', 'test_number(number): test case number')


@pytest.fixture
def my_target(request):
    return request.config.getoption('--target')


def pytest_runtest_setup(item):
    """decide skip or run testcase"""
    marker = item.get_marker('test_number')
    if marker is None:
        return

    opt = item.config.getoption('target')
    if opt is None:
        return

    targets = opt.split(',')
    test_number = str(marker.args[0])
    if test_number not in targets:
        pytest.skip('it is non-target testcase. skip it.')

 

テストコードの実装

今回はテストコードとして、

の3パターンを用意しました。

def test_no_marker():
    print('apple')
    assert True


@pytest.mark.test_number(1)
def test_with_marker():
    print('grape')
    assert True


@pytest.mark.parametrize('kind, code', [
    pytest.param('banana', '123', marks=pytest.mark.test_number(2)),
    pytest.param('pear', '456', marks=pytest.mark.test_number(3)),
])
def test_parameterize_with_marker(kind, code):
    print(f'\n{kind}: {code}')
    assert True

 

テストの実行

独自コマンドラインオプションのtargetを指定しない場合、すべてのテストが実行されました。

$ python -m pytest e.g._add_commandline_option/ -s
...
.apple
.grape
.
banana: 123
.
pear: 456
.

 
target=1とした場合は、独自マーカーの引数に1を渡しているテストケースが実行されました。

また、独自マーカーがないテストも実行されています。

$ python -m pytest e.g._add_commandline_option/ -s --target 1
...
.apple
.grape
.ss

 
@pytest.mark.parametrizeなテストコードもうまく制御されています。

# parametrizeなテストのうち、前者のもの
$ python -m pytest e.g._add_commandline_option/ -s --target 2
...
.apple
.s
banana: 123
.s


# parametrizeなテストのうち、後者のもの
$ python -m pytest e.g._add_commandline_option/ -s --target 3
...
.apple
.ss
pear: 456
.

 

conftest.pyについて

そもそも conftest.py は何だろうと思い調べたところ、以下の解説が詳しかったです。ディレクトリレベルのプラグインと考えれば良さそうです。
python - In py.test, what is the use of conftest.py files? - Stack Overflow

 

ソースコード

GitHubにあげました。e.g._add_commandline_option ディレクトリが今回のものです。
thinkAmi-sandbox/python_pytest-sample

#stapy 第29回みんなのPython勉強会に参加しました & LTしました

10/11にクリーク・アンド・リバー社で開催された、第29回みんなのPython勉強会に参加しました。
みんなのPython勉強会#29 - connpass

いつもはギークラボ長野にて中継を見ていますが、今回は初の現地参加でした。

今回のテーマはデータサイエンスとPythonでした。データサイエンス方面はあまりさわっていないため、いろいろと参考になる話が聞けました。

以下、簡単なメモです。誤っていたらご指摘ください。

目次

 

データサイエンスとPythonの役割

辻真吾さん(Start Python Club)

データサイエンスとそのまわりのライブラリのお話が印象に残りました。

マニアックな関数についてはRの方が強いなど、RとPythonでの機能面の違いについて疑問に思ってたことが分かりました。

 

PySparkで始める並列分散処理

林田千瑛さん(Retty.Inc)

Apache Sparkの概要を知ることができて良かったです。

以下、印象に残ったところです。

  • Apache Sparkは、一台から使える
  • RDDとDataFrameの違い
    • RDDは柔軟、DataFrameの方が速い
  • Apache Sparkを使うなら、データ規模が10GBを超えるあたりから
    • アドテクや異常検知などに向く
  • AWS EMRでは、ノートブックとしてApache Zeppelinが使える
  • AWS EMRからGoogle BigQueryにデータを渡すと転送量が多いため、費用がかかる
  • Apache Sparkには論文があるので、設計思想を知ることができる

 

データサイエンティストを目指す全てのPythonistaのために

中林紀彦さん(SOMPOホールディングス

事業会社における、データサイエンティストの活躍する環境づくりが印象に残りました。

以下、印象に残ったところです。

  • AWSGCPのマルチクラウドで構築
  • 社内データ・社外データ・オープンデータをまとめたメタデータテーブルを用意
    • どこに生データがあるかの検索を容易に
  • ビジネス経験を積むのも重要
    • データをビジネスにどうやって持っていくか、考えることができるため
  • 現場で使ってもらいやすくなるよう、結果をDjangoに組み込んで表現
  • データサイエンティストにとって良い会社
    • データを容易に入手できる会社
    • 分析結果を容易にシステムに組み込めること
    • 「自分は、この会社の何にコミットしているのか」をお互いに説明できる環境

 

LTのスライド(Robot FrameworkでSeleniumを扱いやすくする)

Robot FrameworkでSeleniumを扱いやすくする - slideship.com

プレゼンをする時の準備に手間取ってしまい、余裕なくLTしていたような気がします。事前準備重要ですね。

Robot Frameworkに興味を持っていただけた方もいらっしゃったようで、ありがたいです。

また、使った時のソースコード全体は、GitHubに上げました。
thinkAmi-sandbox/stapy29-sample

 
他にもLTされる方々が多く、いろいろと活発でした。

 
また、今回、Slideshipで初めてスライドを作ってみました。

作った時に感じたことは、

  • シンタックスハイライトが便利
  • ブラウザで動作が、ネットワークがつながってなくても、スライドを使ったプレゼンができる
  • SlideShareやSpeakerDeckのように、ブログへ埋め込む方法はどこかにあるのかな...

です。

 
最後になりましたが、関係者のみなさまありがとうございました。

RobotFramework + SeleniumLibrary + Appiumにて、Genymotion上のChromeを使ってテストする

以前、AndroidChromeを使うテストをRobot Frameworkで書いてみました。
RobotFramework + SeleniumLibraryにて、Android実機上のChromeを使ってテストする - メモ的な思考的な

この時は実機上のChromeを使っていました。

今回は、Androidエミュレータの一種であるGenymotion上のChromeを使って、テストしてみます。

 
目次

 

環境

  • Mac OS X 10.11.6
  • Python 3.6.2
  • RobotFramework 3.0.2
  • SeleniumLibrary 3.0.0b1
  • Node.js 8.4.0
  • Xcode 8.2.1
  • Appium 1.7.1
  • Genymotion 2.10.0

 
上記の環境はすべて構築済とします。

なお、Appiumのインストールは、以下の記事で行ったものを流用しています。
RobotFramework + SeleniumLibrary + Appiumで、iOSシミュレータ上のSafariブラウザでテストする - メモ的な思考的な

 

環境構築

Genymotion上に仮想デバイスを作成

今回は Google Nexus5 - 5.1.0 - API22 - 1080x1920 をセットアップします。

セットアップ終了後、仮想デバイスを起動したままにしておきます。

 

OpenGAppsのChromeをインストール

今回はGenymotoinoのサイトでも紹介されている通り、 OpenGApps を使ってChromeをインストールします。
Genymotion 2.10 – Google Play Services and Play Store Are There!

Google Playを使うにはVariantは nano で良いのですが、Chromeは含まれていません。

そのため、以下の内容でダウンロードします。

Platform Android Variant
x86 5.1 full

 
zipファイルのダウンロードが終わったら、そのzipファイルをGenymotionへとドラッグ&ドロップします。

しばらくすると仮想デバイスへのインストールが終わります。

インストール後、仮想デバイスを再起動すると、Chromeがインストールされています。

 

Robot Frameworkのテストコード実装

実機上でテストしたものと同じソースコードとなります。

*** Settings ***

Library  SeleniumLibrary


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

    # 以下を参考に、Chromeのオプションを追加して、Chromeを起動する
    # https://sites.google.com/a/chromium.org/chromedriver/getting-started/getting-started---android
    ${options} =  evaluate  sys.modules['selenium.webdriver'].ChromeOptions()  sys
    call method  ${options}  add_experimental_option  androidPackage  com.android.chrome
    create webdriver  Chrome  chrome_options=${options}

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

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

    # 検索後を入力してEnter
    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_python_android.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 ***

GoogleでPythonを検索するテスト
    GoogleでPythonを検索してスクリーンショットを撮り、結果を出力する

 

テスト実行

Genymotionの仮想デバイスを起動

シャットダウンしているとテストできないため、起動しておきます。

 

Appiumを起動

ターミナルより起動します。

$ appium
[Appium] Welcome to Appium v1.7.1
[Appium] Appium REST http interface listener started on 0.0.0.0:4723

 

テストを実行

ターミナルより実行します。

$ robot android_chrome.robot 
================
Android Chrome         
================
GoogleでPythonを検索するテスト                                         
Python - ウィキペディア
https://ja.m.wikipedia.org/wiki/Python
Python基礎講座(1 Pythonとは) - Qiita
http://qiita.com/Usek/items/ff4d87745dfc5d9b85a4
Pythonとは - python.jp
https://www.python.jp/about/
Top - python.jp
https://www.python.jp/
【入門者必見】Pythonとは?言語の特徴やシェア、仕事市場を徹底解説 | 侍エンジニア塾ブログ | プログラミング入門者向け学習情報サイト
http://www.sejuku.net/blog/7720
Python 3を使うべきでない場合(なんてない) | プログラミング | POSTD
http://postd.cc/case-python-3/
Pythonに咬まれるな : 注意すべきセキュリティリスクのリスト | プログラミング | POSTD
http://postd.cc/a-bite-of-python/
GoogleでPythonを検索するテスト    | PASS |

テストがパスしました。

また、スクリーンショットも撮影されています。

f:id:thinkAmi:20170928214013p:plain:w400

 

ソースコード

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

SeleniumGrid + RobotFramework + SeleniumLibraryで、VMのWindowsのInternet Explorerを使ってテストする

今まで、

など、Mac上で動作するものに対してテストコードを書いてきました。

 
そんな中、VMWindowsInternet Explorerを使ってテストする機会がありました。

そこで、

を行うよう、SeleniumGrid + RobotFramework + SeleniumLibraryを使ってテストしてみたため、その時のメモを残します。

なお、Selenium Gridについては以下が詳しいです。
» Selenium Gridで複数の実機ブラウザで自動テスト TECHSCORE BLOG

 
目次

 

環境

今回は

という構成にしました。

なお、Selenium Grid自体は、HubとNodeを一つの端末にしても動作します。ターミナルが3つ必要になるくらいです。(Hub用、Node用、テスト実行用)

 

Mac

 

Windows

 

Mac側のSelenium Gridの環境構築

Selenium Grid用のjarファイルのダウンロード

後日AppiumでもSelenium Grid環境を構築するため、Seleniumは3.3.1を使います (現時点の最新は3.5.3)。

PythonライブラリのバージョンとSelenium Gridのバージョンが異なる場合エラーが起きることがあるため、同じバージョンのものをダウンロードします。

今回は過去のバージョンのため、ダウンロードページのprevious releasesより selenium-server-standalone-3.3.1.jar をダウンロードします。

ダウンロードしたzipを展開し、出てきたjarファイルをテスト用ディレクトリに置きます。

 

Selenium Grid Host用の設定ファイルを作成

コマンドラインに設定内容を記述してもよいのですが、今回は設定ファイルを使います。

今回使用するMacにはVM用のネットワークアダプタなど、IPが振られているネットワークアダプタが複数あります。何も設定しないと、LANのネットワークアダプタが使われないことがあります。その場合、Selenium Grid NodeからHubへ接続できず動作しません。

そのため、今回の設定ファイルには、HubのIPアドレスを記載します。

hub_config.json

{
  "host": "192.168.10.103"
}

 

Selenium Grid Hubの起動

Macのターミナルを開き、jarファイルのあるディレクトリで以下を実行します。

$ java -jar selenium-server-standalone-3.3.1.jar -role hub -hubConfig hub_config.json 

21:54:58.285 INFO - Selenium build info: version: '3.3.1', revision: '5234b32'
...
21:54:59.918 INFO - Nodes should register to http://192.168.10.103:4444/grid/register/
21:54:59.918 INFO - Selenium Grid hub is up and running

Hubが起動しました。

http://192.168.10.103:4444/grid/console へアクセスすると、以下のようになりました。

f:id:thinkAmi:20170917215832p:plain

 

VMwareのゲストOSのIP設定をブリッジへと変更

もし、VMwareの設定画面にネットワークアダプタがない場合は、新規に追加します。

その上で、ネットワークアダプタの設定を Macを共有 から ブリッジされたネットワーキング > 自動検出 へと変更します。

これでMacとゲストOSのWindowsIPアドレスが別となりました *1

 

VMのWindows10側のSelenium Gridの環境構築

jarとIEDriverServerのダウンロードと配置

NodeとなるWindowsにも、Hubと同じバージョンのjarファイルおよびIEDriverServerを任意のディレクトリに用意します。

今回用意したものは

  • selenium-server-standalone-3.3.1.jar
    • Hubと同じバージョンのもの
  • IEDriverServer.exe
    • IEDriverServer_Win32_3.3.0.zipを展開したもの
    • Windows10のOSは64bitだが、Downloadsページに32bit IEが推奨されていたため、32bit版のものを使った
    • Internet Explorer 用 WebDriver (Windows)

を同じディレクトリに入れます。

なお、jarと同じディレクトリに置けば、IEDriverServer.exeには特にPATHを通さなくても動作しました。

 

Selenium Grid Node用の設定ファイルを作成

Internet Explorerを動作させるための設定ファイルを記載します。

なお、Selenium3からは configuration というキーを付けるとエラーとなります。
Selenium 3.0.1 Chrome Node configuration - Stack Overflow

また、設定ファイルのデフォルト値は以下に記載されています。 https://github.com/SeleniumHQ/selenium/blob/master/java/server/src/org/openqa/grid/common/defaults/DefaultNodeWebDriver.json

今回はその差分を記載します。

node.json

{
  "capabilities": [
    {
      "browserName": "internet explorer",
      "platform": "WINDOWS",
      "maxInstances": 1,
      "cleanSession": true ,
      "version": "11",
      "browser-version": "11",
      "seleniumProtocol": "WebDriver"
    }
  ],
  "hub": "http://192.168.10.103:4444/grid/register",
  "host": "192.168.10.107",
  "port": 5054,
  "register": true
}

 

Internet Explorerの設定を変更

SeleniumInternet Explorerを使う場合、いくつかの設定が必要になります。

今回は以下のWikiにあるRequired Configurationに従い、設定を行います。
Required Configuration - InternetExplorerDriver · SeleniumHQ/selenium Wiki

設定内容は

  • インターネットオプションのセキュリティタブにある、 保護モードを有効にする にチェックを入れる
  • インターネットオプションの詳細設定にある 拡張保護モードを有効にするチェックを外す
  • IEを起動し、ズームを100%にする
  • Windows10の場合、IEのバージョンは11なので、レジストリに以下を追加する
    • キー:HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Internet Explorer\Main\FeatureControl\FEATURE_BFCACHE
    • 値: 種類 DWORD(32ビット値) 、名前 iexplore .exe 、 データ 0
    • 今回は32bitのIEを使ったが、64bitの場合は別のなのでWikiを参照のこと

です。

 

Selenium Grid Nodeの起動

コマンドプロンプトから起動します。

>java -jar selenium-server-standalone-3.3.1.jar -role node -nodeConfig node.json
22:00:16.200 INFO - Selenium build info: version: '3.3.1', revision: '5234b32'
22:00:17.466 INFO - Registering the node to the hub: http://192.168.10.103:4444/grid/register
22:00:17.497 INFO - The node is registered to the hub and ready to use

Nodeが起動し、Hubに登録されました。

 
この結果、Macのコンソールには

21:59:07.276 INFO - Registered a node http://192.168.10.107:5054
22:00:13.005 INFO - I/O exception (java.net.SocketException) caught when processing request to {}->http://192.168.10.107:5054: Connection reset
22:00:13.006 INFO - Retrying request to {}->http://192.168.10.107:5054
22:00:17.512 INFO - Registered a node http://192.168.10.107:5054
22:00:17.512 WARN - Cleaning up stale test sessions on the unregistered node http://192.168.10.107:5054

と表示されます。

また、Selenium Grid HubのConsoleをブラウザで開くと

f:id:thinkAmi:20170917221316p:plain

に変わりました。

 

Robot Frameworkのテストコードを作成

今回もGooglePythonを検索するテストコードになります。

以前と異なる点は

  • Create Webdriverキーワードで、ブラウザ名を Remote にする
  • command_executor に、Selenium GridのHubの待ち受けURLを指定
  • desired_capabilities に、Selenium GridでIEを動かすためのDesiredCapabilitiesを指定

となります。

なお、Remoteに対するDesiredCapabilitiesの書き方は以下が参考になりました。 robotframework - Opening Chrome browser in Android device using Robot Framework script and chromedriver? - Stack Overflow

 
internet_explorer.robot

*** Settings ***

# Libraryは大文字小文字の区別があるようで、libraryとしてしまうとIDEが認識しない
Library  SeleniumLibrary


*** Keywords ***
GoogleでPythonを検索してスクリーンショットを撮り、結果を出力する
    ${caps} =  create dictionary  browserName=internet explorer  platform=WINDOWS
    create webdriver  Remote  command_executor=http://192.168.10.103:4444/wd/hub  desired_capabilities=${caps}

    # 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っz1
    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 ***

GoogleでPythonを検索するテスト
    GoogleでPythonを検索してスクリーンショットを撮り、結果を出力する

 

テストの実行

準備が整ったため、Macのターミナルよりテストを実行します。

$ robot internet_explorer.robot

を実行すると、VMWindowsでIE11が起動し、GooglePythonを検索します。

テストが進むにつれMacのターミナルに

==============================
Internet Explorer                                                             
==============================
GoogleでPythonを検索するテスト                                         
Python - ウィキペディア
https://ja.wikipedia.org/wiki/Python
Pythonとは - python.jp
https://www.python.jp/about/
Python チュートリアル — Python 3.6.1 ドキュメント
https://docs.python.jp/3/tutorial/index.html
【入門者必見】Pythonとは?言語の特徴やシェア、仕事市場を徹底解説 | 侍 ...
http://www.sejuku.net/blog/7720
Pythonとは?何に使えるの?Pythonの特徴や使い道を…|Udemy メディア
https://udemy.benesse.co.jp/development/python.html
Pythonに関する12300件の投稿 - Qiita
https://qiita.com/tags/Python
Python基礎講座(1 Pythonとは) - Qiita
http://qiita.com/Usek/items/ff4d87745dfc5d9b85a4
初心者でもほぼ無料でPythonを勉強できるコンテンツ10選 - paiza開発日誌
http://paiza.hatenablog.com/entry/2015/04/09/%E5%88%9D%E5%BF%83%E8%80%85%E3%81%A7%E3%82%82%E3%81%BB%E3%81%BC%E7%84%A1%E6%96%99%E3%81%A7Python%E3%82%92%E5%8B%89%E5%BC%B7%E3%81%A7%E3%81%8D%E3%82%8B%E3%82%B3%E3%83%B3%E3%83%86%E3%83%B3%E3%83%8410
Python入門
http://www.tohoho-web.com/python/
Pythonとは - はてなキーワード - はてなダイアリー
http://d.hatena.ne.jp/keyword/Python
GoogleでPythonを検索するテスト    | PASS |

と表示されていきます。

ターミナルにPASSが表示されたところで、VMWindowsのIE11が閉じます。

また、実行ディレクトリに、IEの画面のスクリーンショットも保存されています。

f:id:thinkAmi:20170917222158p:plain

*画像は一部を切り抜いています。

 
以上より、

ができました。

 

参考

ソースコード

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

なお、 hub_config.jsonnode.json も含めています。もし使う場合は、 node.jsonSelenium Grid Nodeに渡し、IPアドレスなどを変更すると良いです。

また、 selenium-server-standalone-3.3.1.jarIEDriverServer.exe は含めていないため、それらはダウンロードしてください。

*1:Macと共有してもSelenium Grid環境を構築できるかもしれませんが、未検証です

RobotFramework + SeleniumLibrary + Appiumで、iOSシミュレータ上のSafariブラウザでテストする

以前、AndroidChromeを使うテストをRobot Frameworkで書いてみました。
RobotFramework + SeleniumLibraryにて、Android実機上のChromeを使ってテストする - メモ的な思考的な

今回は、iOSシミュレータ上のSafariを使うテストをRobot Frameworkで書いてみます。

なお、DesiredCapabilitiesの内容についてはSeleniumWikiに情報があります。
DesiredCapabilities · SeleniumHQ/selenium Wiki · GitHub

 
目次

 

環境

  • Mac OS X 10.11.6
  • Python 3.6.2
  • RobotFramework 3.0.2
  • SeleniumLibrary 3.0.0b1
  • iOS シミュレータ 10.2
  • Node.js 8.4.0
  • Xcode 8.2.1
  • AppiumとSeleniumは、いずれかの組み合わせで動作

 
今回、iOSシミュレータのSafariを使うために、Appium経由で操作してみます。

なお、RobotFrameworkとAppiumを連携するための robotframework-appiumlibrary ライブラリは不要でした。
serhatbolsu/robotframework-appiumlibrary: AppiumLibrary is an appium testing library for RobotFramework

 

環境構築

Node.jsのインストール

Appiumを使うためにはNode.jsが必要なため、Node.jsをインストールします。

 

既存のNode.jsを削除

手元のNode.jsを確認したところ、Node.jsがあったため、アンインストールします。

$ brew uninstall node
Error: Refusing to uninstall /usr/local/Cellar/node/8.1.4
because it is required by heroku 6.12.8, which is currently installed.
You can override this and force removal with:
  brew uninstall --ignore-dependencies node

以前、Heroku Toolbeltをインストールした時のものが残っているようでした。

 
今回、Heroku ToolbeltのNode.jsは後で入れ直すことにして、アンインストールします。

$ brew uninstall heroku
Uninstalling /usr/local/Cellar/heroku/6.12.8... (5,974 files, 30.7MB)
heroku 5.6.1-0976cf3 1 is still installed.
Remove all versions with `brew uninstall --force heroku`.

 
削除しきれていないようなので、Herokuのドキュメントに従って削除します。
Heroku CLI | Heroku Dev Center

$ brew uninstall --force heroku
Uninstalling heroku... (12,942 files, 79.7MB)

# herokuに書いてあった方法で追加削除
$ rm -rf ~/.local/share/heroku ~/.config/heroku ~/Library/Caches/heroku
(特に結果は表示されない)

 
もう一度確認とまだインストールされていたため、そちらもアンインストールします。

$ node -v
v8.1.4

# アンインストール
$ brew uninstall node
Uninstalling /usr/local/Cellar/node/8.1.4... (3,782 files, 44.7MB)

# 確認
$ node -v
-bash: /usr/local/bin/node: No such file or directory

 

nodebrewのインストール

Node.jsもバージョン管理したいなと思ったところ、nodebrewがありました。

そこで、以下を参考にnodebrewをインストールします。
Homebrewからnodebrewをインストールして、Node.jsをインストールするまで - Qiita

$ brew install nodebrew
Updating Homebrew...
==> Auto-updated Homebrew!
Updated 1 tap (caskroom/cask).

==> Using the sandbox
==> Downloading https://github.com/hokaccha/nodebrew/archive/v0.9.7.tar.gz
==> Downloading from https://codeload.github.com/hokaccha/nodebrew/tar.gz/v0.9.7
######################################################################## 100.0%
==> /usr/local/Cellar/nodebrew/0.9.7/bin/nodebrew setup_dirs
==> Caveats
Add path:
  export PATH=$HOME/.nodebrew/current/bin:$PATH

To use Homebrew's directories rather than ~/.nodebrew add to your profile:
  export NODEBREW_ROOT=/usr/local/var/nodebrew

Bash completion has been installed to:
  /usr/local/etc/bash_completion.d

zsh completions have been installed to:
  /usr/local/share/zsh/site-functions
==> Summary
🍺  /usr/local/Cellar/nodebrew/0.9.7: 8 files, 38KB, built in 17 seconds

 

nodebrewのセットアップ

nodebrew setup

# セットアップ
$ nodebrew setup
Fetching nodebrew...
Installed nodebrew in $HOME/.nodebrew

========================================
Export a path to nodebrew:

export PATH=$HOME/.nodebrew/current/bin:$PATH
========================================

~/.bash_profileに追記

export PATH=$HOME/.nodebrew/current/bin:$PATH

.bash_profileを再読込

$ source ~/.bash_profile

 

nodebrewを使ったNode.jsのインストール
$ nodebrew install-binary stable
Fetching: https://nodejs.org/dist/v8.4.0/node-v8.4.0-darwin-x64.tar.gz
######################################################################## 100.0%
Installed successfully

 

使うバージョンを指定
$ nodebrew use stable
use v8.4.0

 

npm init

全部Enterで進めます

$ npm init
This utility will walk you through creating a package.json file.
It only covers the most common items, and tries to guess sensible defaults.

See `npm help json` for definitive documentation on these fields
and exactly what they do.

Use `npm install <pkg>` afterwards to install a package and
save it as a dependency in the package.json file.

Press ^C at any time to quit.
package name: (selenium_appium_sample) 
version: (1.0.0) 
description: 
entry point: (index.js) 
test command: 
git repository: 
keywords: 
author: 
license: (ISC) 
About to write to path/to/robotframework_sample/selenium_appium_sample/package.json:

{
  "name": "selenium_appium_sample",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "author": "",
  "license": "ISC"
}


Is this ok? (yes) 

 

Appiumのインストール

GitHubのREADMEに従い、Appium本体をインストールします。
GitHub - appium/appium: Automation for iOS, Android, and Windows Apps.

$ npm install -g appium

npm WARN deprecated babel-core@5.8.24: Babel 5 is no longer being maintained. Upgrade to Babel 6.
npm WARN deprecated minimatch@2.0.10: Please update to minimatch 3.0.2 or higher to avoid a RegExp DoS issue
npm WARN deprecated line-numbers@0.2.0: Copy its ~20 LOC directly into your code instead.
/Users/you/.nodebrew/node/v8.4.0/bin/appium -> /Users/you/.nodebrew/node/v8.4.0/lib/node_modules/appium/build/lib/main.js

> appium-chromedriver@2.11.2 install /Users/you/.nodebrew/node/v8.4.0/lib/node_modules/appium/node_modules/appium-chromedriver
> node install-npm.js

info Chromedriver Install Installing Chromedriver version '2.28' for platform 'mac' and architecture '64'
info Chromedriver Install Opening temp file to write chromedriver_mac64 to...
info Chromedriver Install Downloading https://chromedriver.storage.googleapis.com/2.28/chromedriver_mac64.zip...
info Chromedriver Install Writing binary content to /var/folders/h0/l5plp4zd3517r988jpm481g00000gn/T/2017815-1009-nx99nt.vp8p/chromedriver_mac64.zip...
info Chromedriver Install Extracting /var/folders/h0/l5plp4zd3517r988jpm481g00000gn/T/2017815-1009-nx99nt.vp8p/chromedriver_mac64.zip to /var/folders/h0/l5plp4zd3517r988jpm481g00000gn/T/2017815-1009-nx99nt.vp8p/chromedriver_mac64
info Chromedriver Install Creating /Users/you/.nodebrew/node/v8.4.0/lib/node_modules/appium/node_modules/appium-chromedriver/chromedriver/mac...
info Chromedriver Install Copying unzipped binary, reading from /var/folders/h0/l5plp4zd3517r988jpm481g00000gn/T/2017815-1009-nx99nt.vp8p/chromedriver_mac64/chromedriver...
info Chromedriver Install Writing to /Users/you/.nodebrew/node/v8.4.0/lib/node_modules/appium/node_modules/appium-chromedriver/chromedriver/mac/chromedriver...
info Chromedriver Install /Users/you/.nodebrew/node/v8.4.0/lib/node_modules/appium/node_modules/appium-chromedriver/chromedriver/mac/chromedriver successfully put in place

> appium-selendroid-driver@1.6.2 install /Users/you/.nodebrew/node/v8.4.0/lib/node_modules/appium/node_modules/appium-selendroid-driver
> node ./bin/install.js

dbug AndroidDriver Getting Java version
info AndroidDriver Java version is: 1.8.0_144
info Selendroid Ensuring /Users/you/.nodebrew/node/v8.4.0/lib/node_modules/appium/node_modules/appium-selendroid-driver/selendroid/download exists
info Selendroid Downloading Selendroid standalone server version 0.17.0 from http://repo1.maven.org/maven2/io/selendroid/selendroid-standalone/0.17.0/selendroid-standalone-0.17.0-with-dependencies.jar --> /Users/you/.nodebrew/node/v8.4.0/lib/node_modules/appium/node_modules/appium-selendroid-driver/selendroid/download/selendroid-server-7cf7163ac47f1c46eff95b62f78b58c1dabdec534acc6632da3784739f6e9d82.jar
info Selendroid Writing binary content to /Users/you/.nodebrew/node/v8.4.0/lib/node_modules/appium/node_modules/appium-selendroid-driver/selendroid/download/selendroid-server.jar.tmp
info Selendroid Selendroid standalone server downloaded
info Selendroid Determining AndroidManifest location
info Selendroid Determining server apk location
info Selendroid Extracting manifest and apk to /Users/you/.nodebrew/node/v8.4.0/lib/node_modules/appium/node_modules/appium-selendroid-driver/selendroid/download
info Selendroid Copying manifest and apk to /Users/you/.nodebrew/node/v8.4.0/lib/node_modules/appium/node_modules/appium-selendroid-driver/selendroid
info Selendroid Cleaning up temp files
info Selendroid Fixing AndroidManifest icon bug

> appium-uiautomator2-driver@0.3.3 install /Users/you/.nodebrew/node/v8.4.0/lib/node_modules/appium/node_modules/appium-uiautomator2-driver
> node ./bin/install.js

dbug AndroidDriver Getting Java version
info AndroidDriver Java version is: 1.8.0_144
info UiAutomator2 downloading UiAutomator2 Server APK v0.1.5 : https://github.com/appium/appium-uiautomator2-server/releases/download/v0.1.5/appium-uiautomator2-server-v0.1.5.apk
info UiAutomator2 downloading UiAutomator2 Server test APK v0.1.5 : https://github.com/appium/appium-uiautomator2-server/releases/download/v0.1.5/appium-uiautomator2-server-debug-androidTest.apk
info UiAutomator2 UiAutomator2 Server APKs downloaded

> appium-windows-driver@0.5.0 install /Users/you/.nodebrew/node/v8.4.0/lib/node_modules/appium/node_modules/appium-windows-driver
> node install-npm.js

Not installing WinAppDriver since did not detect a Windows system

> fsevents@1.1.2 install /Users/you/.nodebrew/node/v8.4.0/lib/node_modules/appium/node_modules/fsevents
> node install

[fsevents] Success: "/Users/you/.nodebrew/node/v8.4.0/lib/node_modules/appium/node_modules/fsevents/lib/binding/Release/node-v57-darwin-x64/fse.node" already installed
Pass --update-binary to reinstall or --build-from-source to recompile

> heapdump@0.3.9 install /Users/you/.nodebrew/node/v8.4.0/lib/node_modules/appium/node_modules/heapdump
> node-gyp rebuild

  CXX(target) Release/obj.target/addon/src/heapdump.o
  SOLINK_MODULE(target) Release/addon.node
+ appium@1.6.5
added 692 packages in 330.588s

 

Appium-doctorのインストール
$ npm install -g appium-doctor

/Users/you/.nodebrew/node/v8.4.0/bin/appium-doctor -> /Users/you/.nodebrew/node/v8.4.0/lib/node_modules/appium-doctor/appium-doctor.js
+ appium-doctor@1.4.3
added 155 packages in 28.769s

 

インストールされた内容を確認

[Node.js] インストール済みのパッケージ一覧を表示する - Qiita

$ npm -g list --depth=0
/Users/you/.nodebrew/node/v8.4.0/lib
├── appium@1.6.5
├── appium-doctor@1.4.3
└── npm@5.3.0

 

Javaまわりの設定を.bash_profileへ追加

Appium-doctorを実行したところ、 JAVA_HOME/bin のエラーが出ていたため、以下を参考に設定を追加します。
Appium Doctor - unable to set JAVA_HOME/bin - Issues/Bugs - Appium Discuss

export JAVA_HOME=/Library/Java/JavaVirtualMachines/jdk1.8.0_144.jdk/Contents/Home
export PATH=$PATH:$JAVA_HOME/bin

 

CarthageをHomebrewでインストール

Appium-doctorを実行したところ、 Carthage でエラーが出ました。

$ appium-doctor

info AppiumDoctor Appium Doctor v.1.4.3
info AppiumDoctor ### Diagnostic starting ###
info AppiumDoctor  ✔ The Node.js binary was found at: /Users/you/.nodebrew/current/bin/node
info AppiumDoctor  ✔ Node version is 8.4.0
info AppiumDoctor  ✔ Xcode is installed at: /Applications/Xcode.app/Contents/Developer
info AppiumDoctor  ✔ Xcode Command Line Tools are installed.
info AppiumDoctor  ✔ DevToolsSecurity is enabled.
info AppiumDoctor  ✔ The Authorization DB is set up properly.
WARN AppiumDoctor  ✖ Carthage was NOT found!
info AppiumDoctor  ✔ HOME is set to: /Users/you
info AppiumDoctor  ✔ ANDROID_HOME is set to: /Users/you/android/
info AppiumDoctor  ✔ JAVA_HOME is set to: /Library/Java/JavaVirtualMachines/jdk1.8.0_144.jdk/Contents/Home
info AppiumDoctor  ✔ adb exists at: /Users/you/android/platform-tools/adb
info AppiumDoctor  ✔ android exists at: /Users/you/android/tools/android
info AppiumDoctor  ✔ emulator exists at: /Users/you/android/tools/emulator
info AppiumDoctor  ✔ Bin directory of $JAVA_HOME is set
info AppiumDoctor ### Diagnostic completed, one fix needed. ###
info AppiumDoctor 
info AppiumDoctor ### Manual Fixes Needed ###
info AppiumDoctor The configuration cannot be automatically fixed, please do the following first:
WARN AppiumDoctor - Please install Carthage. Visit https://github.com/Carthage/Carthage#installing-carthage for more information.
info AppiumDoctor ###
info AppiumDoctor 
info AppiumDoctor Bye! Run appium-doctor again when all manual fixes have been applied!
info AppiumDoctor 

 
Carthageの最新版は、Xcode 8.3系が必要です。

ただ、都合により手元のMacSierraにはできないため、以下を参考に古いバージョンのCarthageをインストールします。
Homebrewで過去のバージョンを使いたい - Carpe Diem

Carthage 0.23.0であれば、Xcode 8.2.1でも動作するようでした。

# ログを確認
$ brew log carthage --oneline
Warning: homebrew/core is a shallow clone so only partial output will be shown.
To get a full clone run:
  git -C "$(brew --repo homebrew/core)" fetch --unshallow
75d2a4a carthage: update 0.25.0 bottle.
4253a70 carthage 0.25.0
4a9efba carthage: update 0.24.0 bottle.
f74d9ba carthage 0.24.0
330abb7 carthage: update 0.23.0 bottle.
9e8ceb0 carthage 0.23.0
6ae4f69 carthage: update 0.22.0 bottle.
80e29a8 carthage 0.22.0
632ebc1 carthage: update 0.21.0 bottle.
2cad486 carthage 0.21.0
6d42f60 carthage: update 0.20.1 bottle.
a98dcba carthage 0.20.1
d3e71df carthage: update 0.20.0 bottle.
2a81ba5 carthage 0.20
3e8dea9 carthage: update 0.19.1 bottle.
75270e7 carthage 0.19.1
016acde gosu: update 1.14.2 bottle.

# HomebrewのFormulaディレクトリへ移動
$ cd /usr/local/Homebrew/Library/Taps/homebrew/homebrew-core/Formula/

# git fetch
$ git fetch --unshallow
remote: Counting objects: 290412, done.
remote: Compressing objects: 100% (128802/128802), done.
remote: Total 290412 (delta 162162), reused 287051 (delta 158817), pack-reused 0
Receiving objects: 100% (290412/290412), 69.61 MiB | 392.00 KiB/s, done.
Resolving deltas: 100% (162162/162162), completed with 3292 local objects.

# ログを再確認
$ brew log carthage --oneline | grep 0.23.0
330abb7 carthage: update 0.23.0 bottle.
9e8ceb0 carthage 0.23.0

 
ハッシュがわかったため、インストールします。

# git checkoutで戻す
$ git checkout 330abb7 carthage.rb 

# brew installでインストールする
$ brew install carthage
==> Downloading https://homebrew.bintray.com/bottles/carthage-0.23.0.el_capitan.bottle.tar.gz
######################################################################## 100.0%
==> Pouring carthage-0.23.0.el_capitan.bottle.tar.gz
==> Caveats
Bash completion has been installed to:
  /usr/local/etc/bash_completion.d

zsh completions have been installed to:
  /usr/local/share/zsh/site-functions
==> Summary
🍺  /usr/local/Cellar/carthage/0.23.0: 64 files, 22.4MB

# Carthageのバージョンを確認
$ carthage --version
Please update to the latest Carthage version: 0.25.0. You currently are on 0.23.0
Unrecognized command: '--version'. See `carthage help`.

 
インストールが終わったため、Homebrewのリポジトリを戻しておきます。

$ git reset HEAD
Unstaged changes after reset:
M   Formula/carthage.rb
$ git checkout .

 
再度確認したところ、OKそうでした。

$ appium-doctor
info AppiumDoctor Appium Doctor v.1.4.3
info AppiumDoctor ### Diagnostic starting ###
info AppiumDoctor  ✔ The Node.js binary was found at: /Users/you/.nodebrew/current/bin/node
info AppiumDoctor  ✔ Node version is 8.4.0
info AppiumDoctor  ✔ Xcode is installed at: /Applications/Xcode.app/Contents/Developer
info AppiumDoctor  ✔ Xcode Command Line Tools are installed.
info AppiumDoctor  ✔ DevToolsSecurity is enabled.
info AppiumDoctor  ✔ The Authorization DB is set up properly.
info AppiumDoctor  ✔ Carthage was found at: /usr/local/bin/carthage
info AppiumDoctor  ✔ HOME is set to: /Users/you
info AppiumDoctor  ✔ ANDROID_HOME is set to: /Users/you/android/
info AppiumDoctor  ✔ JAVA_HOME is set to: /Library/Java/JavaVirtualMachines/jdk1.8.0_144.jdk/Contents/Home
info AppiumDoctor  ✔ adb exists at: /Users/you/android/platform-tools/adb
info AppiumDoctor  ✔ android exists at: /Users/you/android/tools/android
info AppiumDoctor  ✔ emulator exists at: /Users/you/android/tools/emulator
info AppiumDoctor  ✔ Bin directory of $JAVA_HOME is set
info AppiumDoctor ### Diagnostic completed, no fix needed. ###
info AppiumDoctor 
info AppiumDoctor Everything looks good, bye!
info AppiumDoctor 

 

iOS シミュレータの準備

Xcodeを起動し、 Window > Devices より、インストール済のシミュレータ一覧を表示します。

次に左下の + ボタン > Add Simulator よりシミュレータを追加します。

項目名
Simulator Name iOS10.2 for RF
Device Type iPhone 7 Plus
OS Version iOS 10.2

 

Robot Frameworkのテストコード実装

今回はGoogleでログインボタンを押してログイン画面へと遷移するテストを書いてみます。

*** Settings ***

# Libraryは大文字小文字の区別があるようで、libraryとしてしまうとIDEが認識しない
Library  SeleniumLibrary

# テストケースごとにブラウザを閉じる
Test Teardown  close browser

*** Keywords ***
Googleのトップページでスクリーンショットを撮る
    # iOSシミュレータを使うためのDesired Capabilitiesを設定する
    # platformVersionとdeviceNameはXcodeで作成した内容を指定
    ${caps}=  create dictionary  browserName=safari  platformName=iOS  platformVersion=10.2
    ...                          deviceName=iOS10.2 for RF

    # WebDriverにはRemote、command_executorにはAppiumの待ち受けているURL、
    # desired_capabilitiesには作成したDesired Capabilitiesをそれぞれ指定
    create webdriver  Remote  command_executor=http://localhost:4723/wd/hub  desired_capabilities=${caps}

    # Googleのトップページを開く
    go to  https://www.google.co.jp/

    # スクリーンショットを撮る
    capture page screenshot  filename=result_google_top.png


*** TestCases ***

Googleのトップページに関するテスト
    [Tags]  signin
    Googleのトップページでスクリーンショットを撮る

 

テスト実行

Appiumの起動

新しいターミナルを開いて、Appiumを起動します。

$ appium
[Appium] Welcome to Appium v1.6.5
[Appium] Appium REST http interface listener started on 0.0.0.0:4723

 

テストコードの実行

RobotFrameworkのテストを実行します。初回はシミュレータが起動するまでにかなり時間がかかります。

しばらく待つと、以下のようにテストをパスします。

# RobotFrameworkを実行
# iオプションでTag指定(topというタグがついているテストのみ実行)
$ robot -i top ios.robot 
===========================================
Ios
===========================================
Googleのトップページに関するテスト  | PASS |
-------------------------------------------
Ios                             | PASS |
1 critical test, 1 passed, 0 failed

 
また、iOSシミュレータの画面のスクリーンショットが撮られ、テスト実行時のディレクトリへと保存されます。

f:id:thinkAmi:20170915221906p:plain

 

Googleで検索するテスト

Selenium > 3.3.1 & Appium 1.6.5では失敗

続いて、Androidのときと同じようにGooglePythonを検索するテストを書いてみます。

GoogleでPythonを検索してスクリーンショットを撮り、結果を出力する
    ${caps}=  create dictionary  browserName=safari  platformName=iOS  platformVersion=10.2
    ...                          deviceName=iOS10.2 for RF
    create webdriver  Remote  command_executor=http://localhost:4723/wd/hub  desired_capabilities=${caps}
    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_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}

 
実行します。

$ robot -i python ios.robot 
========================================
Ios
========================================
GoogleでPythonを検索するテスト  | FAIL |
WebDriverException: Message: Parameters were incorrect. We wanted {"required":["value"]} and you sent ["text","value","id","sessionId"]
----------------------------------------
Ios                          | FAIL |
1 critical test, 0 passed, 1 failed

テストが失敗しました。

エラーメッセージで検索すると、以下のIssueがありました。
Python Selenium client incompatible with Appium server 1.6.4. · Issue #8253 · appium/appium · GitHub

SendKeyまわりに不具合があるようです。

v1.6.6には取り込まれるそうなので、その時にまた確認することにします。

もしSendKeyまわりを使う場合には、SeleniumやAppiumを古いバージョンにして使う必要がありそうです。

 

Selenium == 3.3.1 & Appium 1.6.5では成功

どのバージョンなら動くかを調べたところ、以下に情報がありました。Selenium3.3.1 にすれば良さそうです。
send_keys -> Message: Parameters were incorrect. We wanted {"required":["value"]} and you sent ["text","sessionId","id","value"] · Issue #162 · appium/python-client · GitHub

 
バージョンを切り替えます。

# seleniumだけ3.3.1、あとは同じ
$ pip list
pip (9.0.1)
robotframework (3.0.2)
robotframework-seleniumlibrary (3.0.0b1)
selenium (3.3.1)
setuptools (28.8.0)

テストを実行してみます。

$ robot -i python ios.robot 
==============================================================================
Ios                                                                           
==============================================================================
GoogleでPythonを検索するテスト                                         
Python - ウィキペディア
https://ja.m.wikipedia.org/wiki/Python
【入門者必見】Pythonとは?言語の特徴やシェア、仕事市場を徹底解説 - 侍エンジニア塾
http://www.sejuku.net/blog/7720
Python基礎講座(1 Pythonとは) - Qiita
http://qiita.com/Usek/items/ff4d87745dfc5d9b85a4
Pythonとは?何に使えるの?Pythonの特徴や使い道を…|Udemy メディア
https://udemy.benesse.co.jp/development/python.html
Python入門
http://www.tohoho-web.com/python/
初心者でもほぼ無料でPythonを勉強できるコンテンツ10選 - paiza開発日誌
http://paiza.hatenablog.com/entry/2015/04/09/%E5%88%9D%E5%BF%83%E8%80%85%E3%81%A7%E3%82%82%E3%81%BB%E3%81%BC%E7%84%A1%E6%96%99%E3%81%A7Python%E3%82%92%E5%8B%89%E5%BC%B7%E3%81%A7%E3%81%8D%E3%82%8B%E3%82%B3%E3%83%B3%E3%83%86%E3%83%B3%E3%83%8410
Python チュートリアル — Python 3.6.1 ドキュメント
https://docs.python.jp/3/tutorial/index.html
Python 3.6.1 ドキュメント
https://docs.python.jp/3/index.html
GoogleでPythonを検索するテスト                                        | PASS |
------------------------------------------------------------------------------
Ios                                                                   | PASS |
1 critical test, 1 passed, 0 failed

成功しました。

スクリーンショットも問題なく撮れています。

f:id:thinkAmi:20170915221930p:plain

 

Selenium == 3.5.0 & Appium 1.7.0では成功 (2017/9/20追記)

Appium1.7.0がリリースされていたため、インストールして試してみました。

# アップデート
$ npm install -g appium
...
+ appium@1.7.0
added 78 packages, removed 110 packages and updated 92 packages in 161.01s

# バージョンを確認
$ appium --version
1.7.0

# Python環境を確認
$ pip list
robotframework (3.0.2)
robotframework-seleniumlibrary (3.0.0b1)
selenium (3.5.0)

 
環境が整いましたので、テストを実行してみます。

$ robot -i python ios.robot 

===============================
Ios
===============================
GoogleでPythonを検索するテスト                                         
Python - ウィキペディア
https://ja.m.wikipedia.org/wiki/Python
Python基礎講座(1 Pythonとは) - Qiita
http://qiita.com/Usek/items/ff4d87745dfc5d9b85a4
【入門者必見】Pythonとは?言語の特徴やシェア、仕事市場を徹底解説 ...
http://www.sejuku.net/blog/7720
Python 3を使うべきでない場合(なんてない) | プログラミング | ...
http://postd.cc/case-python-3/
初心者でもほぼ無料でPythonを勉強できるコンテンツ10選 - paiza開発 .. ...
http://paiza.hatenablog.com/entry/2015/04/09/%E5%88%9D%E5%BF%83%E8%80%85%E3%81%A7%E3%82%82%E3%81%BB%E3%81%BC%E7%84%A1%E6%96%99%E3%81%A7Python%E3%82%92%E5%8B%89%E5%BC%B7%E3%81%A7%E3%81%8D%E3%82%8B%E3%82%B3%E3%83%B3%E3%83%86%E3%83%B3%E3%83%8410
Pythonとは?何に使えるの?Pythonの特徴や使い道を… ...
https://udemy.benesse.co.jp/development/python.html
Python入門
http://www.tohoho-web.com/python/
Python 3.6.1 ドキュメント
https://docs.python.jp/3/index.html
Python チュートリアル — Python 3.6.1 ドキュメント
https://docs.python.jp/3/tutorial/index.html
GoogleでPythonを検索するテスト                                        | PASS |

テストがPASSしました。

Appium1.7.0ではsend_keysの不具合は修正されたようです。

 

Appiumの停止

そのままではAppiumは停止しないため、 Cmd + C で停止させます。

 

ソースコード

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

#pyconjp PyCon JP 2017に参加しました

9/8と9/9に、早稲田大学西早稲田キャンパス63号館で開催された「PyCon JP 2017」に参加しました。
PyCon JP 2017 in Tokyo | Sep 7th – Sep 10th

前回PyCon JPに参加したのは2012年だったようで、5年ぶりの参加でした。
PyCon JP 2012に参加してきました(9/15,16) - メモ的な思考的な

 
以下、簡単な感想を2日間まとめてメモしておきます。

目次

 

Keynote

Peter Wang氏

初日のKeynoteです。遅れて会場入りしたこともあり、既に始まっていました。

自分の知識不足もあり、データサイエンス系のところはなかなか難しかったですが、コミュニティのスタイルはその国にあった形があるというところが印象に残りました。

 

Masaaki Horikoshi氏

こちらは2日目のKeynoteです。

OSS活動は良いと分かっていてもハードルが高く感じるために、それを下げてくれるKeynoteでした。初めてOSS活動を開始する時に参考になるお話がいろいろとありました。

特に、貢献先は自分の興味があるOSSに絞ること、解決しやすいIssueから取り組みはじめると良いというのが印象に残りました。

 

参加したトーク

Pythonとパッケージングと私 (Atsushi Odagiri氏)

setup.pyとか雰囲気で書いているため、パッケージングまわりを知りたくて参加しました。

setuptoolsの30.3.0からsetup.cfgが使えるようになるとのことで、こうなればsetup.pyがスッキリして良さそうでした。

ただ、仮想環境を作った時のsetuptoolsのバージョンがまだそこまでいっていないため、実際に使えるようになるのはもう少し先というのが残念です…

 

メディア会議

技術書はどのように作られるのか気になって参加しました。

パネルディスカッション形式で、本を作る裏側が見えて良かったです。

 

Djangoフレームワークのユーザーモデルと認証 (Shinya Okano氏)

昔、Djangoの認証系をさわったことがあったので、知識を最新にアップデートするために参加しました。

class-based viewでいろいろと書けるようになったのは本当に嬉しい感じです。

 

len()関数がオブジェクトの長さを手にいれる仕組み (Takayuki Shimizukawa氏)

Pythonのコアな話はなかなか日常に登場しないので、気になって参加しました。

関数とアダプタの関係、そしてチェック機構はアダプタ側に持たせていると知り、ためになりました。

Pythonにおけるプロトコルの概念や一覧の紹介もあり、こちらも参考になりました。

 

How (and Why) We Speak in Unicode (Devon Peticolas氏)

しばらく前に 'ascii' codec can't decode byte なエラーと格闘したことがあったので、PythonUnicodeまわりを知ろうと思い参加しました。

Unicodeに至るまでの歴史の解説の中に、スライドの中にアスキーアートが登場したり、日本語の事情が含まれていたりと、なかなかおもしろかったです。

 

Secrets of a WSGI master (Graham Dumpleton氏)

WSGIまわりをさわったことがあったため、WSGIの知識を深めたくて参加しました。

PEP3333に基づいたWSGIの説明と、mod_wsgi の使い方と設定、mod_wsgi-expressの例やDockerでの利用方法がありました。

mod_wsgiをさわる機会はまだまだありそうなので、いろいろと参考になったのと、今後使う時は参照しようと思いました。

 

OpenAPIを利用したPythonWebアプリケーション開発 (Takuro Wada氏)

Swaggerという単語は聞いたことがあったので、具体的な内容を知りたくて参加しました。

Open APIと、現在のバージョン(2.0と3.0)、また各言語向けのライブラリが紹介されていて参考になりました。

 

Python におけるドメイン駆動設計(戦術面)の勘どころ (Junya Hayashi氏)

ドメイン駆動設計をどうPythonに落とし込めばよいのかよく分かっていないため、それを知りたくて参加しました。

概念から始まり、Pythonで実装する時にダメな実装方法と良い実装方法の解説がありました。

サンプルソースコードも公開されていたため、あとでコードを読みつつ理解したいと思います。

 

機械学習におけるデータの再現性について (Yuichiro Someya氏)

データの再現性についてどのように実現するのだろうと気になって参加しました。

再現性におけるつらいところが分かるとともに、 akagi というライブラリにより解決した部分の解説がありました。

それでもまだつらい部分は残るようで、この解決はまた大変そうだと感じました。

 

Pythonをとりまく並行/非同期の話 (tell-k氏)

Pythonの並行/非同期についてふわっとしか理解していないため参加しました。

用語の定義から実装例まで分かりやすい解説があり、とてもためになりました。

資料もきちんとまとまっていたのがありがたいです。今後このあたりをさわるときは、もう一度読み返そうと思います。

 

AWS APIGateway + Python Lambda + NEologdで作るサーバレス日本語形態素解析API (Satoru Kadowaki氏)

実装を例に、工夫したところや苦労したところの情報共有がありました。

NEologdの辞書を充実させる方向ではなく、前処理を頑張る方向での実装でした。前処理の頑張りにより辞書が変わっても結果は変わらなそうなのが印象に残りました。

 

ブース

トーク以外の時間は、主にブースにて過ごしました。

Python/Django + HoloLensなアプリをメインに体験していただきました。

 

その他

ごはん

今回は、2日間を通して、朝・昼・おやつ、そして1日目のパーティと、会場の外に出ることなくごはんをいただけました。

いずれもボリューム満点な上、お昼ごはんは種類の選択肢もありました。ありがたい限りです。

 

モノタロウ侍さん

モノタロウ侍さんにポーズをいただきました。

 

PyCon JP 2018について

既に開催が決まっていました。

2018/9/17(月・祝)~9/18(火)、場所は大田区産業プラザPiO(Plaza Industry Ota)とのことです。
交通アクセス|大田区産業プラザPiO

 
最後になりましたが、PyCon JP 2017を運営してくださったみなさま、ありがとうございました。

Bitbucketにて、あるブランチのファイルの最新版をURLで指定する

Bitbucketにて、あるブランチのファイルの最新版をURLで指定しようとして悩んだのでメモ。

 
通常、BitbucketのあるブランチのファイルのURLには、Gitのコミットハッシュが含まれます。

例えば、 python-bitbucket というライブラリのREADME.rstについてブラウザでリンクをクリックしていくと

のように、 src の下に、Gitのコミットハッシュが含まれます。

 
Gitのコミットハッシュを使わない方法を調べたところ、stackoverflowに情報がありました。
hyperlink - Link latest file on Bitbucket Git repository - Stack Overflow

src/[branch_name]/path/to/file を指定すれば良いとのことです。

 
そのため、python-bitbucketのブランチ release/0.10 のREADME.rstの最新版の場合には、

となります。

ブランチ名に / が含まれていても、そのままURLに書けば良いようです。