【Python】【Windows】AWS lambdaとseleniumを用いてサーバーレスGUI操作負荷テストを行う方法 

#AWS lambdaを用いてサーバーレスでGUIの負荷をかけたい！
・Jmeter等のソフトウェアでは機能毎に分かれているシステムに対して負荷がかけずらい
　ログインはこっちの機能を使って、DBはこっち使って・・ってやってると一貫した動作を何百回も実行したい

・windowsProじゃなくても負荷テストしたい！人のためにdockerは使いません


#使用したもの及び環境
・Windows10
・AWS lambda
・AWS Cloud9
・VScode(開発環境)
・Python3.7
  -Selenium
  -headless-chrome
  -chromedriver
・heroku(負荷対象)
  -Flask(負荷対象ページ)


##苦労ポイント
①Windows環境なのでlambda（EC2）のOSであるAmazonLinux 2と環境に差異が出て実行出来ないSelenium
②実行権限が無いと怒られるchromedriver　【error: Message: ‘chromedriver’ executable needs to be in PATH】
③pathが無いと怒られるchromedriver 【unknown error: cannot find Chrome binary】
④謎の【selenium.common.exceptions.WebDriverException: Message: chrome not reachable】


##負荷対象ページ
https://hello-flask-post.herokuapp.com/
flaskとherokuで作りました


##ソースコード
負荷をかけるプログラム rush.py

```rush.py
# -*- coding: utf-8 -*-
import time
from selenium import webdriver
from selenium.webdriver.common.keys import Keys

def rush(*args, **kwargs) :

    options = webdriver.ChromeOptions()
    options.binary_location = "./bin/headless-chromium"
    options.add_argument("--headless")
    options.add_argument("--no-sandbox")
    options.add_argument("--single-process")
    options.add_argument('--disable-dev-shm-usage')

    
    #webdriverの実行　実行ファイルとChromeWebDriverが無い場合は第一引数でpathを指定
    #第一引数は特に不要なのですが、lambdaの環境だと指定してあげないと苦労ポイント③になります。
    driver = webdriver.Chrome(executable_path="./bin/chromedriver",chrome_options=options)

    #bootstrap-flaskで作った負荷かける用ページ
    driver.get('https://hello-flask-post.herokuapp.com/') 

    ###負荷をかけるために入力フォームでの送信を行う
    #入力フォームの必須事項
    name_form= driver.find_element_by_id('name')
    name_form.send_keys('rush')
    
    email = driver.find_element_by_id('email')
    email.send_keys('sample@sample.com')
    
    subject = driver.find_element_by_id('subject')
    subject.send_keys('lambda')
    
    #入力メッセージ
    subject = driver.find_element_by_name('message')
    subject.send_keys('test')
    
    #送信ボタン
    driver.execute_script('arguments[0].scrollIntoView();', driver.find_element_by_id('btnContactUs'))
    driver.find_element_by_id('btnContactUs').send_keys(Keys.RETURN)
```
##cloud9での作業
適当にフォルダ切って、その中にrush.pyをぶちこむ

```
sudo pip install selenium -t ./
```

ここからlambdaで動かす用のheadless-chromeを取得し、binというフォルダを切り、その中にぶち込む
https://github.com/adieuadieu/serverless-chrome/releases

ここからchromedriverを取得し、同様にbinにぶち込む
https://chromedriver.storage.googleapis.com/index.html?path=2.44/

以下の画像の様に、全てに実行権限を付与した後、zip化を行う

![2019y01m06d_013542571.jpg](https://qiita-image-store.s3.amazonaws.com/0/280980/d0d5e8c8-1783-275c-89d6-8e4b55cd9b40.jpeg)



以上で、苦労ポイント①,②は解決

##lambdaの環境

![2019y01m04d_000456750.jpg](https://qiita-image-store.s3.amazonaws.com/0/280980/1a22d81a-19dc-206c-6f5c-71f93d400d42.jpeg)



以上で実行準備は整いました。


##lambda関数の実行
特にEC2を立ち上げるまでもなくcloud9で実行しちゃいます
以下のコマンドで非同期（リターンを待たず実行を繰り返す）実行を行います

```
for i in {1..10}; do aws lambda invoke --function-name <functionname> --region <lambda関数のlocation> --invocation-type Event output.txt; done```
```
![2019y01m06d_015616903.jpg](https://qiita-image-store.s3.amazonaws.com/0/280980/8d1abd99-ca01-2a2b-27ac-387f3d46b271.jpeg)

flaskの方はこのようにpostされたら日付をプリントするようにしています
![2019y01m06d_021557810.jpg](https://qiita-image-store.s3.amazonaws.com/0/280980/f9226da2-6b3a-83e5-4537-4aeda4bc1951.jpeg)

logの方は![2019y01m06d_021716971.jpg](https://qiita-image-store.s3.amazonaws.com/0/280980/517edf70-6ada-b7aa-d83a-885a330be5b1.jpeg)
![2019y01m06d_021722454.jpg](https://qiita-image-store.s3.amazonaws.com/0/280980/277280b4-d883-7401-8666-7d979d7ad3f7.jpeg)
![2019y01m06d_021724033.jpg](https://qiita-image-store.s3.amazonaws.com/0/280980/13f4e0ec-ada9-1529-fa9d-c6e91138ea46.jpeg)

日付が出力されていることがわかり、うまくpost出来ているようです。

##まとめ
上記の手法でlamdbaを用いたGUI操作型負荷テストが行える！（ワ○ップ並の総評）

やはりLamdbaに乗せて実行出来るようになるまでが難しいですね

あとseleniumを使う点で「このボタンクリックできねー！」ってのが会ったらchromeの拡張機能のseleniumを入れると
ボタン要素が簡単に取れます

ちなみに苦労ポイント④は　chromedriverとheadless-chromeの相性が悪かったみたいで2.44を2.43のchromedriverに変更したら無事実行できるようになりました。

##github
今回のプログラムを以下の場所に配置しておきましたので、ご自由にお使いください。
https://github.com/Yishida05/lambda_stresstest

zipを落としてくだされば、そのままlambdaに配置して使えます。

質問や意見等ありましたらなんでもコメントください。