UI自動化の限界を補う


UI自動化の限界
UI自動化テストを実装する過程で、すぐにいくつかの制限が発生します.
たとえば、Naver Shoppingの購入プロセスをUI自動化テストとして実装したとします.
SeleniumまたはAppは、Elementを探して作成したテストケースを実行するように努力します.ただし、エレメントが正常に認識されているが、特定のAPIのStatus Codeにエラーが発生したり、特定のリソースを取得できなくなったりして商品情報を表示できない場合はどうなりますか?
UI自動化テストコードは、エラーによってリソースを取得できなくても、別名が認識され、事前に作成されたテストスクリプトに問題がないため、PASSを処理します.
どうやってこの状況を補うのでしょうか?browsermobproxyを使ってみました.browsermobproxyはProxyサーバであると考えられる.HTTPコンテンツをキャプチャし、パフォーマンスデータをHARファイルにエクスポートすることができます.特にSeleniumとともに使用することができ、UI自動化の限界を補うことができる.
例えば、このような動作が可能である

  • Seleniumオートメーションコードを実行する前に、Pythonコードでbrowsermobproxyサーバフローティングを実現します.
  • Selenium自動化コードを実行します.

  • Selenium自動化コードが終了すると、browsermobproxyサーバがシャットダウンされ、HARファイルが生成される.

  • HARファイル内のHTTP要求セット、応答を分析することによってエラーを決定する.
  • Seleniumを単独で使用する場合と何が違いますか?browsermobproxyは、Seleniumによって自動化コードを実行し、送信および受信されたHTTP通信をキャプチャする.キャプチャされたHARファイルを開き、Status Codeに400または500エラーの履歴があるかどうか、および受信されていないリソースファイルがあるかどうかを確認します.
    したがって、Seleniumは、UIをテストしながら、browsermobproxyとともにHTTP応答を検証することができる.
    どのように実現しますか?テストしてみましょう.

  • まずbrowsermobproxyファイルをダウンロードして解凍します(リンク)
    (解凍フォルダを使用する->bin->browsermob-proxy妖女座)

  • Pythonプロジェクトを生成しpipをインポート
  • pip install browsermobproxy
  • 単純コードの作成とテスト
    bmp_setting.py:プロキシサーバの実行と応答データ処理を実現する方法
    from browsermobproxy import Server
    import psutil
    import time
    from selenium import webdriver
    
    def process_kill(name):
        """중복 실행중인 프로세스 종료"""
    
        for proc in psutil.process_iter():
            if proc.name() == name:
                proc.kill()
    
    def capture_network_traffic(url):
        """프록시 서버 시작 및 네트워크 트래픽 캡쳐"""
    
        server = Server(path="/Users/taekyeong.jung/Downloads/browsermob-proxy-2.1.4/bin/browsermob-proxy",
                        options={'port': 8787})
        server.start()
        time.sleep(1)
        proxy = server.create_proxy()
        time.sleep(1)
    
        chrome_options = webdriver.ChromeOptions()
        chrome_options.add_argument("--headless")
        chrome_options.add_argument("--proxy-server={0}".format(proxy.proxy))
        chrome_options.add_argument('--ignore-certificate-errors')
    
        driver = webdriver.Chrome(executable_path="/Users/taekyeong.jung/Desktop/workspace/chromedriver",
                                  chrome_options=chrome_options)
    
        proxy.new_har() # options={'captureContent': True} https://github.com/lightbody/browsermob-proxy
    
        driver.get(url)
        driver.quit()
        server.stop()
        return proxy.har
    
    def check_response(response):
        """응답 데이터 가공"""
        entries = response['log']['entries']
    
        errors = []
        i = 0
        while i < len(entries):
    
            if entries[i]['response']['status'] >= 400: # http response 값이 400 이상이면 errors 배열에 추가
    
                dic = {
                        'method':     entries[i]['request']['method'],
                        'url':        entries[i]['request']['url'],
                        'status':     entries[i]['response']['status'],
                        'statusText': entries[i]['response']['statusText'],
                        'time':       entries[i]['time']
                    }
    
                errors.append(dic)
            else:
                pass
    
            i = i + 1
    
        for i in errors:
            print(i)
    test.py : bmp_setting.pyで定義した方法を使用してテストコードを作成してみます.
    import bmp_setting as Setup
    
    
    site = [
        'https://www.myrealtrip.com/',
        'https://flights.myrealtrip.com/',
        'https://www.myrealtrip.com/accommodations',
        'https://www.myrealtrip.com/rentacar',
        'https://www.myrealtrip.com/experiences/'
        ]
    
    # 중복된 프로세스 제거
    Setup.process_kill("browsermob-proxy")
    
    # 프록시 서버 실행 후 네트워크 트래픽 캡쳐
    for i in site:
        response = Setup.capture_network_traffic(i)
        Setup.check_response(response)
    
    結果
    下図に示すように、status codeは400以上のやつを濾過した.Seleniumと併用することで、UIテストの限界を補い、テストの自動化とレポートの受信を実現できます.
    {'method': 'GET', 'url': 'https://d32w679339tzui.cloudfront.net/landscapes/4750_large_square_1609204670.jpg?1609204670', 'status': 404, 'statusText': 'Not Found', 'time': 1579}
    {'method': 'GET', 'url': 'https://d32w679339tzui.cloudfront.net/landscapes/4744_large_square_1609204668.jpg?1609204668', 'status': 404, 'statusText': 'Not Found', 'time': 1458}
    {'method': 'GET', 'url': 'https://d32w679339tzui.cloudfront.net/landscapes/162_large_square_1609201732.jpg?1609201732', 'status': 404, 'statusText': 'Not Found', 'time': 1458}
    {'method': 'GET', 'url': 'https://d32w679339tzui.cloudfront.net/landscapes/4751_large_square_1609204671.jpg?1609204671', 'status': 404, 'statusText': 'Not Found', 'time': 1489}
    {'method': 'GET', 'url': 'https://d32w679339tzui.cloudfront.net/landscapes/770_large_square_1609202023.jpg?1609202023', 'status': 404, 'statusText': 'Not Found', 'time': 1462}
    {'method': 'GET', 'url': 'https://d32w679339tzui.cloudfront.net/landscapes/4672_large_square_1609204639.jpg?1609204639', 'status': 404, 'statusText': 'Not Found', 'time': 1471}
    {'method': 'GET', 'url': 'https://d32w679339tzui.cloudfront.net/landscapes/4606_large_square_1609204589.jpg?1609204589', 'status': 404, 'statusText': 'Not Found', 'time': 423}
    
    reference
    https://github.com/lightbody/browsermob-proxy#getting-started-standalone