نحوه استفاده از Selenium و کاربرد آن در بارگذاری صفحات – بخش دوم

آفلاین
user-avatar
عرفان حشمتی
23 شهریور 1400, خواندن در 8 دقیقه

تعدادی معیار وجود دارد که در طول فرایند توسعه و انتشار هر محصول نرم‌افزاری در نظر گرفته می‌شوند. یکی از این معیارها "تجربه کاربری" است که بر سهولت استفاده مشتریان از محصول شما متمرکز شده است.  در این مقاله قصد داریم به شما نشان دهیم چگونه می‌توانید زمان بارگذاری صفحه را توسط Selenium برای تست خودکار مرورگر اندازه گیری کنید.

تست اتوماسیون برای اندازه گیری زمان بارگذاری صفحه با Selenium

می‌توانید برای اندازه گیری عملکرد یک صفحه وب در طی یک دوره زمانی از Selenium استفاده کنید. نتایجی که از Navigation Timing API به دست می‌آید می‌تواند برای بهبود زمان بارگذاری صفحه با تست Selenium و همچنین محک زدن این نتایج در برابر عملکرد وب رقبا مورد استفاده قرار گیرد. اگرچه بین صفحه اصلی و ویژگی‌های ارائه شده توسط دو وب سایت یا برنامه وب تفاوت‌های قابل مشاهده‌ای وجود دارد، بازهم مهم است که سرعت بارگذاری صفحه نسبت به رقبا برابر باشد (در صورتی که بهتر نباشد).

علاوه بر ردیابی و رتبه بندی عملکرد صفحه وب، از Selenium می‌توان برای ثبت آمار صفحه نیز استفاده کرد تا بتواند در سمت کلاینت پیشرفت‌هایی داشته باشد. تا آنجا که به سمت سرور نیز مربوط شود، می‌توان با استفاده از زیرساخت‌های مناسب عملکرد مطلوبی به دست آورد.

مثال 1 - ثبت آمار زمان بندی صفحه وب با استفاده از Navigation Timing API

بیایید نگاهی به مثالی بیندازیم که در آن از پایتون همراه با فریمورک Selenium برای ثبت آمار مهم در مورد صفحه وب (به عنوان مثال lambdatest.com) استفاده می‌شود. این مثالی است که می‌توانید برای اندازه گیری زمان بارگذاری صفحه در Selenium از آن بهره بگیرید.

''' Loosely based on the example code in http://www.obeythetestinggoat.com/
how-to-get-selenium-to-wait-for-page-load-after-a-click.html
'''
'''
Import the necessary packages required for execution
'''
from selenium import webdriver

''' Chrome web driver interface
'''
hyperlink = "http://lambdatest.com"
driver = webdriver.Chrome()
driver.get(hyperlink)

''' Use Navigation Timing  API to calculate the timings that matter the most '''   
 
navigationStart = driver.execute_script("return window.performance.timing.navigationStart")
responseStart = driver.execute_script("return window.performance.timing.responseStart")
domComplete = driver.execute_script("return window.performance.timing.domComplete")

''' Calculate the performance'''
backendPerformance_calc = responseStart - navigationStart
frontendPerformance_calc = domComplete - responseStart
 
print("Back End: %s" % backendPerformance_calc)
print("Front End: %s" % frontendPerformance_calc)
 
driver.quit()

برای شروع نمونه‌ای از web-driver کروم ایجاد شده و صفحه تحت تست در مرورگر باز می‌شود. ما از Performance Timing API استفاده می‌کنیم تا از زمان درخواست از مرورگر، مدت زمان صرف شده در هر رویداد را به دست آوریم. گزینه execute_script برای اجرای همزمان کد جاوااسکریپت در پنجره فعلی استفاده می‌شود.

برای دمو از معیارهای زیر استفاده کرده‌ایم:

  • navigationStart - این ویژگی زمان صرف شده را پس از اتمام unloading صفحه قبلی توسط کاربر بر می‌گرداند. اگر قبل از بارگذاری صفحه جدید سندی وجود نداشته باشد، navigationStart همان مقدار fetchStart را برمی‌گرداند.
  • responsStart - این ویژگی به محض دریافت اولین بایت از سرور یا از منابع محلی / حافظه پنهان برنامه، زمان را برمی‌گرداند.
  • domComplete - این ویژگی زمان را قبل از اینکه میزان آماده بودن صفحه فعلی روی "complete" تنظیم شود، برمی گرداند. status.ateState در حالت "complete" نشان می‌دهد که تجزیه صفحه کامل شده و تمام منابع مورد نیاز صفحه بارگیری می‌شوند. در بخش بعدی مثالی از domComplete خواهیم دید.

window.performance.timing.navigationStart، window.performance.timing.responseStart وwindows.performance. timing.domComplete گزینه‌های Timing Navigation هستند که به عنوان آرگومان‌هایی به execute_script() منتقل می‌شوند. اندازه گیری زمان هم بر حسب میلی ثانیه است.

همچنین ما از Eclipse به عنوان IDE برای توسعه و تست کد استفاده کرده‌ایم. برای اجرای کد کلیدهای ترکیبی CTRL + F9 را فشار دهید. خروجی زیر اجرای کد بالا را به همراه زمان صرف شده در فعالیتهای فرانت-اند و بک -اند صفحه وب نشان می‌دهد.

مثال 2 - استفاده از رابط WebDriverWait برای جستجوی عناصر در یک صفحه وب

ما به یک مثال دیگر می‌پردازیم که در آن یک صفحه وب را بارگیری کرده و به دنبال وجود عنصر div-id در صفحه هستیم. div-id را برای مدت زمان 5 ثانیه جستجو می‌کنیم. پس از بارگیری صفحه، div-id (در این مثال: owl-example) به مدت 5 ثانیه جستجو می‌شود. پس از آن اگر div-id در صفحه وب وجود نداشته باشد، یک استثنا نشان داده می شود. تمام ماژول‌های لازم نیز در ابتدا ایمپورت می‌شوند.

from selenium import webdriver
from selenium.common.exceptions import TimeoutException
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.by import By

''' Create a Chrome webdriver instance''' 
driver = webdriver.Chrome()
#driver = webdriver.Firefox()

''' Open the webpage under test'''
driver.get('http://lambdatest.com')
timeout = 5

''''' Test case 1 - The required div-id is not present on the web-page ''''' 
#while True:
try:
    element_present = EC.presence_of_element_located((By.ID, 'owl-example-1'))
    WebDriverWait(driver, timeout).until(element_present)
    print("1 - Element is present on the page")
#        break
except TimeoutException as ex:
    print("1 - Timed out waiting for page to load " + str(ex))
#        break

''''' Test case 2 - The required div-id is not present on the web-page '''''
#while True:
try:
    element_present = EC.presence_of_element_located((By.ID, 'owl-example'))
    WebDriverWait(driver, timeout).until(element_present)
    print("2 - Element is present on the page")
#        break
except TimeoutException as ex:
    print("2 - Timed out waiting for page to load " + str(ex))
#        break

''' Free up the resources'''
driver.close()
driver.quit()

مشابه مثال قبلی ما رابط Webdriver را مقداردهی اولیه می‌کنیم. صفحه وب تحت آزمایش صفحه اصلی LambdaTest است - lambdatest.com. مدت زمان هم 5 ثانیه تنظیم شده است. دو مورد آزمایشی وجود دارد که جزئیات آن در زیر ذکر شده است.

  • Test case 1 - صفحه وب در حال بارگیری برای وجود div-id بررسی می‌شود. با استفاده از رابط WebDriverWait جستجو به مدت 5 ثانیه انجام می‌گردد. اگر owl-example-1 در صفحه وجود نداشت، یک exception نشان داده می‌شود.
  • Test case 2 - شرط مورد نظر همان Test case 1 است، با این تفاوت که div-id تحت جستجوی "owl-example" می‌باشد.

همانطور که انتظار میرفت اولین مورد آزمایشی شکست می‌خورد، زیرا div-id مورد جستجو در صفحه وب مورد آزمایش وجود ندارد. زمان جستجو پس از 5 ثانیه پایان می‌یابد. از طرف دیگر مورد آزمایشی دوم عبور کرده، زیرا ‘owl-example’ در صفحه وب وجود دارد. برای تأیید این موضوع لطفا به منبع LambdaTest مراجعه کنید. (که همان صفحه هم مورد آزمایش ماست)

سناریوهایی وجود دارد که هنگام بارگیری یک صفحه وب نیاز به انجام عملیاتی دارید، یعنی وضعیت status.readyState به عنوان "complete". این عملیات میتواند با کلیک کردن روی لینک یا کلیک کردن روی یک دکمه یا هر عملیات دیگر انجام شود. این می‌تواند یک وضعیت دشوار باشد، زیرا ممکن است سناریوهایی وجود داشته باشد که تعداد کمی از صفحه وب با استفاده از AJAX (جاوااسکریپت ناهمزمان و XML) در سمت کلاینت به صورت غیر همزمان بارگیری شود. ما روی عملیاتی که صفحه وب جدید بارگیری می‌شود تمرکز می‌کنیم. در این بخش از آموزش تست Selenium نگاهی داریم به مکانیزمی که برای بررسی بارگیری کامل صفحه وب مورد استفاده قرار می‌گیرد.

مثال 3 - تشخیص تکمیل بارگیری صفحه با pytest و Selenium

Selenium دارای شرایطی داخلی است که به آن پیاده سازی staleness_of و wait_for گفته می‌شود. staleness_of عنصر کلاس Selenium selenium.webdriver.support.expected_condition است. staleness_of تا زمانی که یک عنصر به DOM متصل نشود، منتظر خواهد ماند. در زیر اجرای کلاس آورده شده ‌است:

class selenium.webdriver.support.expected_conditions.staleness_of(element)

element عنصر واقعی در صفحه وب است که منتظر می‌ماند. اگر عنصر به DOM متصل باشد، False را برمی‌گرداند، در غیر این صورت True را برمی‌گرداند. ما از فریمورک pytest استفاده خواهیم کرد. در مثال زیر ازcontextmanager  استفاده شده که به تخصیص و آزاد سازی منابع مورد نیاز در صورت لزوم کمک میکند.

''' Import the 'modules' that are required for execution '''
''' In this example, we make use of pytest framework along with Selenium '''
import pytest
import pytest_html
from selenium import webdriver
from selenium.webdriver.chrome.options import Options
from selenium.webdriver.common.keys import Keys
from time import sleep
from contextlib import contextmanager
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support.expected_conditions import \
    staleness_of

@pytest.fixture(params=["chrome"],scope="class")
def driver_init(request):
    if request.param == "chrome":
        web_driver = webdriver.Chrome()
    request.cls.driver = web_driver
    yield
    web_driver.close()

@pytest.mark.usefixtures("driver_init")
class BasicTest:
    pass
class Test_URL(BasicTest):
        def test_open_url(self):
            self.driver.get("https://www.lambdatest.com/")
            print(self.driver.title)
            sleep(5)

        @contextmanager
        def wait_for_page_load(self, timeout=30):
            #Search for the div-id owl-example
            old_page = self.driver.find_element_by_id('owl-example')  
            yield
            WebDriverWait(self.driver, timeout).until(
                staleness_of(old_page)
            )
        
        def test_click_operation(self):
            # Wait for a timeout duration of 10 seconds, after which we perform a CLICK operation
            with self.wait_for_page_load(timeout=10):
                self.driver.find_element_by_link_text('FREE SIGN UP').click()
                print(self.driver.execute_script("return document.readyState"))

در ()wait_for_page_load جستجو برای div-id owl-example انجام شده است. همچنین از WebDriverWait در ترکیب با ExpectedCondition برای دستیابی به شرایط Explicit Wait استفاده می‌شود. driver و timeout نیز به عنوان آرگومان منتقل می‌شوند. سپس صبر می‌کنیم تا زمان عنصر پایان یابد. در صورت عدم وجود عنصر مورد جستجو یعنی owl-exampl، یک TimeoutException نشان داده می‌شود. به این ترتیب میزان ماندگاری عنصر را بررسی می‌کنیم.

در ()test_click_operation، صفحه وب lambdatest.com بارگیری می‌شود و پس از آن انتظار برای حداکثر مدت زمان 10 ثانیه انجام می‌گردد. این از ()wait_for_page_load استفاده می‌کند تا بررسی شود عنصر owl-example در صفحه وب stale نیست. هنگامی که صفحه وب در داخل timeout بارگذاری می‌شود، بررسی می‌کنیم که آیا عنصری وجود دارد که متن FREE SIGN UP را داشته باشد، این دکمه‌ای است که به صفحه ثبت نام لینک می‌دهد. در آخر با استفاده از ویژگی Document.readyState وضعیت صفحه وب را بررسی می‌کنیم. وقتی مقدار آن تغییر می‌کند، یک رویداد readystatechange به شی document ارسال می‌شود.

سه حالت ممکن loading، interactive و complete است. اگر بارگیری صفحه و منابع وابسته آن به پایان رسیده باشد، Document.readyState حالت complete را می‌گیرد. در مثال ما اگر صفحه به طور کامل بارگیری شود، یک کلیک دکمه انجام می‌شود که در نهایت ما را به صفحه ثبت نام LambdaTest می‌برد.

برای اجرا از دستور py.test استفاده می‌کنیم که در آن verbose فعال بوده و capture-- نیز روی no است.

بسته به بازار هدف و مرورگری که بیشترین میزان بازدید را برای شما فراهم می‌کند، باید یک ماتریس تست ایجاد کنید تا تست مرورگر را به صورت سازمان یافته انجام دهد. تست محصول با مرورگر به شما در یافتن موارد ارزشمندی که می‌تواند برای بهبود زمان بارگذاری صفحه استفاده شود، کمک می‌کند. به جای ایجاد زیرساخت محلی برای انجام این تست‌ها می‌توانید از LambdaTest استفاده کنید که ابزار تست مرورگر مقیاس پذیر را در Cloud ارائه می‌دهد.

جمع بندی

اندازه گیری زمان بارگذاری صفحه برای محصولات مبتنی بر وب بسیار مهم است، چرا که تأثیر مستقیمی بر تجربه کاربر دارد. همچنین در مورد بهینه سازی کلی محصول مهم است که صفحات وب را به گونه‌ای طراحی کنید تا زمان بارگذاری صفحه حداقل مقدار باشد. این امر می‌تواند تبدیلات مورد انتظار از محصول را بهبود بخشد.

Navigation Timing API در اندازه گیری زمان بارگذاری صفحه نقش اساسی دارد. برای بهینه سازی می‌توانید از خروجی تولید شده توسط این APIها استفاده کنید. window.performance شی performance را که اطلاعات مهمی در مورد صفحه فعلی می‌دهد، بر می‌گرداند. این می‌تواند همراه با فریمورک Selenium مورد استفاده قرار گیرد. اندازه گیری زمان بارگذاری صفحه با Selenium از این جهت اهمیت دارد که یک صفحه وب می‌تواند در انواع مختلف و نسخه‌های متفاوت مرورگر با هم فرق داشته باشد. از این رو تمرکز بر بهینه سازی سرعت صفحه محصول مورد نظر در مرورگرها و سیستم‌عامل‌ها برای داشتن تجربه بهتر مشتری بسیار ضروری است.

منبع

چه امتیازی به این مقاله می دید؟
خیلی بد
بد
متوسط
خوب
عالی

دیدگاه‌ها و پرسش‌ها

برای ارسال دیدگاه لازم است، ابتدا وارد سایت شوید.

در حال دریافت نظرات از سرور، لطفا منتظر بمانید

در حال دریافت نظرات از سرور، لطفا منتظر بمانید

آفلاین
user-avatar
عرفان حشمتی @heshmati74
مهندس معماری سیستم های کامپیوتری، طراح و توسعه دهنده وب سایت
دنبال کردن

گفتگو‌ برنامه نویسان

بخشی برای حل مشکلات برنامه‌نویسی و مباحث پیرامون آن وارد شو