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

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

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

下記のように`ActionChains`の`move_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()
```


## ポイント２： 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
```



## ポイント３：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+'"]'
        )
    )

```

## ポイント４：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

## サンプルソース
https://github.com/ttn1129/legacy-application-testable-module-demo

以上です。