[Python] How can i improve my speed in my automation test? (python, pylenium + pytest)

Discussão em 'Python' iniciado por Stack, Abril 19, 2025.

  1. Stack

    Stack Membro Participativo

    I'm new to Python and learning test automation. I’ve written a UI test using Pylenium that goes through an educational blog site and does the following:

    Opens each category from a dropdown

    Checks the left-side menu and collects all tabs

    For each tab, it:

    Opens the tab

    Checks the tab name and the number of courses shown in parentheses

    Iterates through paginated content and counts the actual number of courses on each page

    Compares the actual total count across all pages to the expected count from the tab label

    The test works correctly, but it takes over 2 minutes (0:02:14) to complete.

    My main question is:

    How can I speed this up? Is it possible to optimize the structure.

    page url: https://intellipaat.com/blog/ai/

    from selenium.webdriver.support.select import Select
    from selenium.webdriver.common.by import By
    from loguru import logger
    from pylenium.driver import Pylenium

    class Blog:
    def __init__(self, py: Pylenium):
    self.py = py
    self.py.visit("https://intellipaat.com/blog/ai/")

    def getOptions(self):
    self.py.wait().until(lambda _: self.py.get("#catdropdown"))
    dropdown = Select(self.py.get("#catdropdown").webelement)
    options = [(opt.text.strip(), opt.get_attribute("data")) for opt in dropdown.options]
    logger.info(f"Dropdown options fetched: {[opt[0] for opt in options]}")
    return options

    def openeCategory(self, category_name, category_url):
    logger.info(f" Checking category: {category_name} → {category_url}")
    self.py.visit(category_url)
    self.py.wait().until(lambda _: self.py.getx('//*[@id="tutorial-single-left"]/div[2]').should().be_visible())

    class TabContent:
    def __init__(self, py: Pylenium):
    self.py = py
    self.tabContent = self.get_tabContent()
    self.active_pane = self.get_active_pane()
    self.pages_raw = self.get_pages_raw()
    self.pages_filtered = self.get_pages_filtered()

    def get_tabContent(self):
    return self.py.get("#cat-tabContent")

    def get_active_pane(self):
    return self.tabContent.get(".tab-pane.active")

    def get_pages_raw(self):
    pagination = self.active_pane.get(".pagination")
    pages = pagination.webelement.find_elements(By.CSS_SELECTOR,".page-numbers") #py.find is so slow for some reason ;-;
    return pages

    def get_pages_filtered(self):
    return [el for el in self.pages_raw if el.text.strip() not in ["NEXT »", "« Previous"]]

    def get_page_count(self):
    if len(self.pages_filtered) != 0:
    return int(self.pages_filtered[-1].text.strip())

    return 0

    def go_to_next_page(self):
    next_button = next(
    (el for el in self.pages_raw if "next" in el.get_attribute("class").split() and "page-numbers" in el.get_attribute("class").split()),None)
    try:
    if next_button:
    next_button.click()
    else:
    print("Next button not found!")
    except Exception as e:
    print(f"Couldn't click next button: {e}")

    class page:
    def __init__(self, py: Pylenium, active_pane):
    self.py = py
    self.active_pane = active_pane
    self.CurseCount = self.get_pageContentCount()
    logger.info(f"Detected {self.CurseCount} courses on current page.")

    def get_pageContentCount(self):
    return len(self.active_pane.get(".row").webelement.find_elements(By.CSS_SELECTOR,".col-lg-4.col-md-6"))

    class LeftMenu:
    def __init__(self, py: Pylenium):
    self.py = py
    self.name = self.getName()
    self.tabs = self.getTabs()
    logger.info(f"Left menu name: {self.name} | Tabs found: {len(self.tabs)}")

    def getName(self):
    cat_left_top = self.py.getx('//*[@id="tutorial-single-left"]/div[2]')
    return cat_left_top.getx('.//h1').text().strip()

    def getTabs(self):
    cat_left_top = self.py.getx('//*[@id="tutorial-single-left"]/div[2]')
    return cat_left_top.findx('.//div/a')

    class Tabs:
    def __init__(self, py: Pylenium, tabs_elements):
    self.py = py
    self.tabs_elements = tabs_elements
    self.count = self.get_tab_count()

    def get_tab_count(self):
    return len(self.tabs_elements)

    def openTab(self, tabId):
    logger.info(f"Opening tab index: {tabId}")
    return self.tabs_elements[tabId].click()

    class Tab:
    def __init__(self, py: Pylenium, tab_element):
    self.py = py
    self.tab_element = tab_element
    self.name = self.get_name()
    self.count_tag = self.get_count_of_elements_tag()
    logger.info(f"Tab initialized → {self.name}: {self.count_tag} items")

    def get_name(self):
    return self.tab_element.text().split("(")[0].strip()

    def get_count_of_elements_tag(self):
    return int(self.tab_element.getx('.//span').text().strip().replace("(", "").replace(")", ""))


    def test_blog(py: Pylenium):
    blog = Blog(py)
    options = blog.getOptions()
    for category_name, category_url in options:
    blog.openeCategory(category_name, category_url)
    left_menu = blog.LeftMenu(py)
    Remembered_left_menu_name = left_menu.name
    left_menu_tabs_elements = left_menu.getTabs()
    RememberedTabss = left_menu.Tabs(py, left_menu_tabs_elements)
    RememberedTabs = [RememberedTabss.Tab(py, el) for el in left_menu_tabs_elements]
    for i in range(len(RememberedTabs)):
    logger.info(f"Opening Tab {i}: {RememberedTabs.name}")
    left_menu = blog.LeftMenu(py)
    assert Remembered_left_menu_name == left_menu.name
    tabs = left_menu.Tabs(py, left_menu.getTabs())
    tab = tabs.Tab(py, tabs.tabs_elements)
    tabcontent = blog.TabContent(py)
    pagescount = tabcontent.get_page_count()
    logger.info(f" Pagecount: {pagescount} on tab '{tab.name}'")
    if pagescount > 0:
    numberofcurses = 0
    for pagenumber in range(pagescount):
    logger.info(f"➡️ Loading page {pagenumber + 1}/{pagescount}...")
    tabcontent = blog.TabContent(py)
    page = tabcontent.page(py, tabcontent.active_pane)
    numberofcurses += page.CurseCount
    for a in range(len(RememberedTabs)):
    tabs = left_menu.Tabs(py, left_menu.getTabs())
    assert RememberedTabs[a].name == tabs.Tab(py, tabs.tabs_elements[a]).name
    assert RememberedTabs[a].count_tag == tabs.Tab(py, tabs.tabs_elements[a]).count_tag
    tabcontent.go_to_next_page()
    logger.info(f"✅ Total courses found across all pages on tab '{tab.name}': {numberofcurses}")
    assert numberofcurses == RememberedTabs.count_tag
    else:
    logger.warning(f"⚠️ Single page only. Expected: {RememberedTabs.count_tag}, Found: {tabcontent.page(py, tabcontent.active_pane).CurseCount}")
    for a in range(len(RememberedTabs)):
    tabs = left_menu.Tabs(py, left_menu.getTabs())
    assert RememberedTabs[a].name == tabs.Tab(py, tabs.tabs_elements[a]).name
    assert RememberedTabs[a].count_tag == tabs.Tab(py, tabs.tabs_elements[a]).count_tag
    if (len(RememberedTabs) - 1) > i:
    tabs.openTab(i + 1)


    • Opens the blog URL and fetches all category options from the dropdown menu.
    • Iterates through each category:
    • Navigates to the category URL.
    • Reads the left-side tab menu, including tab names and the course count shown next to them.
    • For each tab inside the category:
    • Opens the tab.
    • Calculates how many pages of content it contains using the pagination component.
    • Visits each page and counts the number of visible course blocks.
    • Sums the total count and compares it against the expected count shown in the tab label (e.g., "Courses (15)").
    • Also re-validates tab names and course counts after each page change to ensure DOM consistency.
    • Asserts that:
    • The total number of courses found across pages matches the expected count.
    • The tab labels and counts remain stable between navigations.

    The test works correctly, but it takes over 2 minutes (0:02:14) to complete.

    Continue reading...

Compartilhe esta Página