もがき系プログラマの日常

もがき系エンジニアの勉強したこと、日常のこと、気になっている技術、備忘録などを紹介するブログです。

PythonでSelenium動かしてみた。

参考サイト

前書き

こんばんは。僕です。

pythonが楽しくて色々と触ってます。

今回は前々から触りたかったSeleniumpythonで動かしてみたいと思います。

下準備

seleniumのinstall

$ pip install selenium
Collecting selenium
  Downloading selenium-3.9.0-py2.py3-none-any.whl (942kB)
    100% |████████████████████████████████| 952kB 694kB/s 
Installing collected packages: selenium
Successfully installed selenium-3.9.0

ChromeDriverのinstall

$ brew install chromedriver
==> Downloading https://chromedriver.storage.googleapis.com/2.35/chromedriver_mac64.zip
######################################################################## 100.0%
==> Caveats
To have launchd start chromedriver now and restart at login:
  brew services start chromedriver
Or, if you don't want/need a background service you can just run:
  chromedriver
==> Summary
🍺  /usr/local/Cellar/chromedriver/2.35: 4 files, 11.3MB, built in 4 seconds

実行

サンプルコード書いてみる

以下サンプルコードでmain.pyとして保存します。

from selenium import webdriver

driver = webdriver.Chrome()
driver.get('https://twitter.com')
driver.save_screenshot('sample.png')
driver.quit()

python main.pyで実行すると、スクリーンショットsample.pngとして保存されます。

f:id:kojirooooocks:20180216041239p:plain

こんな簡単にできるんですね。 これは楽しい。

次はフォームの入力とSubmitを試してみます。 Twitterログインしてみます。

from selenium import webdriver
driver = webdriver.Chrome()

driver.get('https://twitter.com')
mail_form = driver.find_element_by_name('session[username_or_email]')
pass_form = driver.find_element_by_name('session[password]')
mail_form.send_keys('Twitterのメールアドレス')
pass_form.send_keys('Twitterのパスワード')
driver.find_element_by_class_name('js-submit').click()
driver.save_screenshot('sample.png')

python main.pyで実行すると、スクリーンショットsample.pngとして保存されます。

f:id:kojirooooocks:20180216041715p:plain

ログインできました!

2段階認証を設定している意識高い人には通用しないですが、、、

面白いですね。

もう少し使えるように。

指定のページを開くことと、フォームのログイン、submitは出来るようになったので、もっと実践的に、JS制御が効いているようなフォームで、ここのフォームの値がこれの場合は、このフォームは入力できなくなるみたいなところで使えるかやってみたいです。

そこで、本来入力できないはずなのに、入力できちゃってたら、スクリーンショットとって終了とか。テストっぽいことをやってみます。

ざっと簡単にこんなHTML作ってみました。

JSに疎い僕はバリバリjQueryとか使っちゃいます。

<!DOCTYPE html>
<html>
<head>
    <title>test</title>
</head>
<body>
    <div class="movice_rental">
        <label>映画を借りる?</label>
        <select name="movie_rental_select">
            <option value="0">選択してください</option>
            <option value="1">借りる</option>
            <option value="2">借りない</option>
        </select>
    </div>

    <div class="movie_title">
        <label>映画一覧</label>
        <select name="movie_title_select">
            <option value="0">選択してください</option>
            <option value="1">アニマルプラネット</option>
            <option value="2">海底鬼岩城</option>
            <option value="3">のび太と恐竜</option>
            <option value="4">ワンニャン時空伝</option>
        </select>
    </div>

    <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
    <script>
        $("select[name='movie_rental_select']").change(function() {
            if ($(this).val() == 2) {
                $(".movie_title").hide();
            } else {
                $(".movie_title").show();
            }
        });
    </script>
</body>
</html>

このHTML自体は正常に動いちゃうのですが、今回やりたいはエラーのテストなので、指定の値の場合には、指定のフォームが消えるJSを書いたと思ってたけど、書いてなかったという状況を作るため、JS部分を変更します。

        $("select[name='movie_rental_select']").change(function() {
            if ($(this).val() == 2) {
                // 要素のスペルミス
                $(".movieeeeeee_title").hide();
            }
        });

次はseleniumpythonコードの記述です。

# -*- coding: utf-8 -*-
from selenium import webdriver
from selenium.webdriver.support.ui import Select

driver = webdriver.Chrome()

driver.get('HTMLファイルへのパス')
movie_rental_select_form = driver.find_element_by_name('movie_rental_select')
movie_rental_select      = Select(movie_rental_select_form)
movie_title_select_form = driver.find_element_by_name('movie_title_select')
movie_title_select      = Select(movie_title_select_form)

# 一度映画リストのフォームをdisabledにする
movie_rental_select.select_by_value('2')

# 本来はフォームが出てないのでセットできないはずだけどセットしてみる
movie_title_select.select_by_value('3')
if movie_title_select.first_selected_option.get_attribute("value") == '3':
    # valueがセットできているということは、本来意図しない動きのためスクリーンショットを取って終了
    print("[ERROR]movie_title_selectに値をセットできてしまいました!!")
    driver.save_screenshot('sample.png')
    driver.close()

実行すると以下のようなエラーが出ました。

$ python main.py 
[ERROR]movie_title_selectに値をセットできてしまいました!!

f:id:kojirooooocks:20180216041834p:plain

スクリーンショットも取れてました。

すばらしい!!

あとがき

いや。こんなおもしろいものだとは思わなかったです。

現状お仕事を頂いている会社さんではJenkinsが導入されており、Jenkins上からBeanStalkコマンドライン(ebコマンド)でデプロイしています。

運用しているサービスの性質上JSがふんだんに使われている箇所もあるのですが、昔から運用しているサービスなので巷で流行りのJSのテストなどは入っていません。

せめて新たに作成するページや更新するページは、簡単にでもUIテストを自動化させたいなと思っています。

それに、まだまだjQueryとは離れらないサイトなので、こういった昔からあるツールも相性良いかなと。

まぁ、そのためにはEC2上にChromeDriverとか入れないとダメなんですが、コチラに大変参考になる記事を上げてくれている方がいましたので、近々やりたいなと思います。

ではでは。