🕰️

Seleniumと通信環境が悪い状態の試験

2022/01/29に公開

目的

Selenium + Pythonを用いてなるべく通信環境が悪い状態の試験を行う。
以下の読者を対象とする

  • pythonの基本的な操作を行えること
  • seleniumの基本的な操作を行えること
  • webアプリケーションの開発経験があること

手動で通信環境の悪い試験を行う方法

手動試験で通信環境の悪いネットワーク環境を再現した試験を行う場合、2つの方法がある。

  • OS全体の通信状態を設定する
  • ブラウザの開発者ツールを使って通信状態を設定する

OS全体の通信状態を設定する

macの場合はNetwork link conditionerを使用する。
http://fushiroyama.hatenablog.com/entry/2018/02/21/120937

Windowsの場合はClumsyを使用する。
https://jagt.github.io/clumsy/index.html

linuxの場合はlinuxはtc & netemを使用する。
https://man7.org/linux/man-pages/man8/tc-netem.8.html

この手法のメリットはOS全体の通信状態を悪くするため、ブラウザだけでなくネイティブアプリの試験にも使用できることである。
このメリットは同時にデメリットになる。たとえばネットワークドライブをマウントしている場合、フリーズする場合があるし、リモートデスクトップで操作している場合も正常に動作しなくなる。

ブラウザの開発者ツールを使って通信状態を設定する。

Chrome97の場合

ディベロッパーツールのネットワークタブにて「その他のネットワークの状態」アイコンを押下する。

ネットワークスロトリングを押下して任意の状態を選ぶ。

追加により任意の状態を追加することが可能

Firefox96の場合

ウェブ開発ツールのネットワークタブにて「帯域制限なし」のリストを変更する

https://developer.mozilla.org/ja/docs/Tools/Network_Monitor/Throttling

Seleniumで通信環境の悪い試験を行う方法

今回はChromeを対象としてSeleniumで通信環境が悪い状況での試験を行う方法について紹介する。

ChromeDriverを使用してローカルのchromeを操作する

ローカルのChromeに対して通信環境の設定を行うにはset_network_conditionsを使用する。

from selenium import webdriver
from selenium.webdriver import Chrome
from selenium.webdriver.common.by import By
import datetime
chromeOptions = webdriver.ChromeOptions()
chromeOptions.add_argument('--headless')
chromeOptions.add_argument('--disable-gpu')
chromeOptions.add_argument('--no-sandbox')
chromeOptions.add_argument("--lang=ja")
driver = Chrome(options=chromeOptions)
driver.set_network_conditions(
  offline = False,
  latency = 10000, # 10秒遅延させる
  download_throughput = 500 * 1024,
  upload_throughput = 500 * 1024
)
print(datetime.datetime.now())
driver.get('https://needtec.sakura.ne.jp/')
print(driver.find_element(by=By.TAG_NAME, value='h1').text)
print(datetime.datetime.now())
driver.quit()

RemoteDriverを使用してリモートのchromeを操作する

RemoteDriverの場合、set_network_conditionsが使用できないので、send_command_and_get_resultを直接POSTしてNetwork.emulateNetworkConditionsを直接実行する

from selenium import webdriver
from selenium.webdriver.common.by import By
import datetime
import json
chromeOptions = webdriver.ChromeOptions()
chromeOptions.add_argument('--headless')
chromeOptions.add_argument('--disable-gpu')
chromeOptions.add_argument('--no-sandbox')
chromeOptions.add_argument("--lang=ja")

def sendCommand(driver, cmd, params={}):
    resource = "/session/%s/chromium/send_command_and_get_result" % driver.session_id
    url = driver.command_executor._url + resource
    body = json.dumps({'cmd': cmd, 'params': params})
    response = driver.command_executor._request('POST', url, body)
    return response.get('value')

driver = webdriver.Remote('http://127.0.0.1:4444/wd/hub', chromeOptions.to_capabilities())

res = sendCommand(
    driver,
    'Network.emulateNetworkConditions',
    dict({
        'offline': False,
        'latency': 10000, #10秒遅延
        'downloadThroughput': 500 * 1024,
        'uploadThroughput': 500 * 1024
    })
)
print(res)
print(datetime.datetime.now())
driver.get('https://needtec.sakura.ne.jp/')
print(driver.find_element(by=By.TAG_NAME, value='h1').text)
print(datetime.datetime.now())
driver.quit()

参考

・Add Vendor specific commands for Remote webdriver #7914
https://github.com/SeleniumHQ/selenium/issues/7914

・Enable execute_cdp for webdriver.Remote ? #8672
https://github.com/SeleniumHQ/selenium/issues/8672

Discussion