Python
AWS
負荷テスト
lambda
サーバーレス

【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

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

lambdaの環境

2019y01m04d_000456750.jpg

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

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

flaskの方はこのようにpostされたら日付をプリントするようにしています
2019y01m06d_021557810.jpg

logの方は2019y01m06d_021716971.jpg
2019y01m06d_021722454.jpg
2019y01m06d_021724033.jpg

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

まとめ

上記の手法でlamdbaを用いたGUI操作型負荷テストが行える!(ワ○ップ並の総評)

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

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

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

github

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

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

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