特殊なフレームワークで Python Selenium を動かした時のつまずき


Legacy な WebApplication でも Python Selenium のテストを動かしたい

alert、フレームワークのsubmit 制御などなどつまずきましたが、いろいろ調べて、検証したところ、データの作成、ボタンクリック、アラートの確認、などフレームワーク特有の挙動をする要素の操作もできましたので、覚書でまとめます。

ポイント1: submit を Javascript で発火できないときの対応

通常動くはずのクリック時のイベントが Javascript が制御されて動かなかったり、などなどフレームワーク等の理由から、submit がサーバーに送れない場合がありましたので、ActionChain を使用することで解決しました。

下記のようにActionChainsmove_to_element(要素)で、要素までカーソルを動かし、click を実行する操作をプログラミングすることで、Javascript での操作に依存せず、HTMLのクリックイベントを実行することができました。

example.py
from selenium.webdriver.chrome.webdriver import WebDriver
from selenium.webdriver.common.action_chains import ActionChains
from selenium.webdriver.remote.webelement import WebElement

def clickElement(driver:WebDriver, element:WebElement)->None:
    actionsClickElement = ActionChains(driver)
    actionsClickElement.move_to_element(element) #成功
    actionsClickElement.click()
    actionsClickElement.perform()

ポイント2: alert の test のscreenshotを取りたい

通常のWebDriverを介したブラウザ の 画面出力だと、window.alert のスクリーンショットが取れないようでした。
https://stackoverflow.com/questions/38719337/not-able-to-take-screenshot-of-alert-box-in-selenium-using-python

根本的な解決ではないですが pillow を使用することで、ディスプレイのスクリーンショットを取ってしまう処理にすることで、代替することはできるようでした。
http://e-yuki67.hatenablog.com/entry/2017/02/12/152759

example.py
from selenium.webdriver.chrome.webdriver import WebDriver
from PIL import ImageGrab
import os

screenshotDirectoryName = 'tmp'
screenshotBasePath = './'+screenshotDirectoryName+'/'

def screenshotOfDisplay(driver: WebDriver, filename: str = 'screenshotOfDisplay.png'):
    makeDirectoryIfNotExist(screenshotDirectoryName)
    path = screenshotBasePath + filename
    print(path)
    img = ImageGrab.grab()
    img.save(path)
def makeDirectoryIfNotExist(directoryName:str):
    if not os.path.exists(directoryName):
        os.mkdir(directoryName)
    return

pillow のインストールは python3.7.4 だと pip install PIL だと失敗するようなので、下記でインストーしました。
https://stackoverflow.com/questions/32772596/pip-install-pil-fails

pip install pillow

ポイント3:radio ボタン の値設定 は、Element をクリックする

checked を true にするよりも、クリックして値を設定した方が処理が複雑にならず、シンプルなようでした。
https://stackoverflow.com/questions/21322116/using-selenium-in-python-to-click-select-a-radio-button

example.py
from selenium.webdriver.chrome.webdriver import WebDriver
from selenium.webdriver.remote.webelement import WebElement

def checkRadioWithNameSearchInsideElement(driver:WebDriver, targetElement:WebElement, searchName:str, value)->None:
    clickElement(
        driver,
        targetElement.find_element_by_xpath(
            './/input[@type="radio" and starts-with(@name,"'+searchName+'") and @value="'+value+'"]'
        )
    )

ポイント4:Select の値の設定

selenium.webdriver.support.select.Select を用いてselect に対して値を設定できました。
https://a-zumi.net/python-selenium-select/

example.py
from selenium.webdriver.remote.webelement import WebElement
from selenium.webdriver.support.select import Select

def selectOptionValue(targetSelectElement:WebElement, selectValue)->None:
    Select(targetSelectElement).select_by_value(selectValue)
    return

参考

ディレクトリが無かったら作成する処理は下記の記事を参考にさせて頂きました。
https://akamist.com/blog/archives/3013

Windows への python selenium の導入については下記の記事を参考にさせて頂きました。
https://qiita.com/egplnt/items/98b0702e3e6ed1814497

サンプルソース

以上です。