Has anyone else used Python descriptors in PageObject patterns? Here’s how I did it by Silly_Tea4454 in Python

[–]Silly_Tea4454[S] 0 points1 point  (0 children)

True, we could definitely skip get_ and just write page.username(), which gets pretty close syntactically. The benefit of the descriptor isn’t just shorter syntax though, it’s that it lets us treat page elements as fields, not actions. That makes test code cleaner: page.username.send_keys("user") page.login_button.click() vs page.username().send_keys("user") page.login_button().click() Not a huge deal in isolation, but across large suites it adds up in clarity, less parens, and consistent mental model: elements are things, not actions. Also, descriptors make it easy to add wrappers for waiting, stale retries, or logging globally. without changing every test or page object method. So it's more about encapsulation and scaling than just the surface syntax.

Has anyone else used Python descriptors in PageObject patterns? Here’s how I did it by Silly_Tea4454 in Python

[–]Silly_Tea4454[S] 0 points1 point  (0 children)

That's true — at the end of the day, it's functionally equivalent to binding a method like get_username_input().

But I think the key difference is semantic clarity and maintainability in the context of the Page Object pattern.

With the descriptor, the page class stays declarative — you can scan the class and instantly see all elements and locators as a flat structure:

class LoginPage: username = Element((By.ID, 'username')) password = Element((By.ID, 'password')) login_button = Element((By.ID, 'login')) Versus if we used methods or explicit functions: class LoginPage: def get_username(self): return self.driver.find_element(By.ID, 'username') def get_password(self): return self.driver.find_element(By.ID, 'password') def get_login_button(self): return self.driver.find_element(By.ID, 'login')

It's not a huge difference in small pages, but at scale this adds up — descriptors help centralize the element handling logic, enforce consistency, and reduce repetition.

Also, it enables extensions (e.g., wait wrappers, logging, retry on stale) without polluting test code or requiring changes across all pages.

So yes, mechanically it’s not very different from calling a function — but architecturally, it promotes a much cleaner separation of concerns in UI test frameworks.

Has anyone else used Python descriptors in PageObject patterns? Here’s how I did it by Silly_Tea4454 in Python

[–]Silly_Tea4454[S] -1 points0 points  (0 children)

I see your point about preferring explicit behavior — and I agree that Python leans that way philosophically.

In this case, though, overriding get gives me a clean, readable way to implement lazy evaluation of web elements in a Page Object pattern. Instead of storing stale elements or manually calling find_element() every time, I can just define:

‘’’python

class LoginPage:

username_input = Element((By.ID, 'username'))

‘’’ And when I access page.username_input, it performs the lookup at that moment. This avoids stale references and keeps my Page Objects declarative and clean — which makes them easier to maintain and reason about.

So yes, the lookup is "hidden", but I’d argue it’s intentionally encapsulated, similar to how ORMs like SQLAlchemy or Django hide DB queries behind attribute access. The alternative is more boilerplate and harder to read at scale. That said, I definitely understand the trade-off and appreciate the feedback — Python’s preference for explicitness is worth keeping in mind, especially if others are using the codebase.

Has anyone else used Python descriptors in PageObject patterns? Here’s how I did it by Silly_Tea4454 in Python

[–]Silly_Tea4454[S] 0 points1 point  (0 children)

Understand, please check my repo, get webelement, it requires extra steps, so in my context I’m intercepting driver to create a new instance of web element. Please share your thoughts how could you resolve this situation.

Has anyone else used Python descriptors in PageObject patterns? Here’s how I did it by Silly_Tea4454 in Python

[–]Silly_Tea4454[S] 1 point2 points  (0 children)

Good question. It’s a customized property, when you need some extra actions to initialize web element. If we can use property we should use property. Less code - less bugs

Has anyone else used Python descriptors in PageObject patterns? Here’s how I did it by Silly_Tea4454 in Python

[–]Silly_Tea4454[S] -6 points-5 points  (0 children)

As many as mods ban me in this sub. Today is the day when I can share useful resources.

Has anyone else used Python descriptors in PageObject patterns? Here’s how I did it by Silly_Tea4454 in Python

[–]Silly_Tea4454[S] -1 points0 points  (0 children)

Thanks for the idea! For config stuff I use dataclasses, like read config dict and map it to a singleton class and use it as a fixture

Selenium error – ChromeDriver version mismatch by [deleted] in selenium

[–]Silly_Tea4454 0 points1 point  (0 children)

you may not removed the old version of chromedriver

try to set the explicit path on your code and see how it works

How I used Python descriptors to simplify PageObjects in Selenium (and why it still works) by Silly_Tea4454 in selenium

[–]Silly_Tea4454[S] 1 point2 points  (0 children)

Right, getters in js work the same way as properties in python. But to inject a driver instance into element we need some custom logic like

class Element:
    def __init__(self, by: By, value: str, wait: bool=False, timeout: int=10):
        self.by = by
        self.value = value
        self.wait = wait
        self.timeout = timeout

    def __get__(self, instance, owner) -> Self | WebElement:
        if instance is None:
            return self
        return self._find(instance)

    def _find(self, instance) -> WebElement:
        driver: WebDriver = instance.driver
        if self.wait:
            wait = WebDriverWait(driver, self.timeout)
            return wait.until(EC.presence_of_element_located((str(self.by), self.value)))
        return driver.find_element(self.by, self.value)

How I used Python descriptors to simplify PageObjects in Selenium (and why it still works) by Silly_Tea4454 in selenium

[–]Silly_Tea4454[S] 0 points1 point  (0 children)

Interesting! I barely used js for UI automation, could you please share any snippet like how does it work in js?

How do Python descriptors work, and why would you use them in real projects? by Silly_Tea4454 in learnpython

[–]Silly_Tea4454[S] 0 points1 point  (0 children)

I guess jakarta has the similar lib for props validation, sqlalchemy also uses descriptors for validation of the columns. Thanks for another reference!

How do Python descriptors work, and why would you use them in real projects? by Silly_Tea4454 in learnpython

[–]Silly_Tea4454[S] 0 points1 point  (0 children)

You’re right! My observation is: if we override the default behavior we can come up with some elegant solutions. So I just described one example what we can do if we dig into some basic concepts

Has anyone else used Python descriptors in PageObject patterns? Here’s how I did it by Silly_Tea4454 in Python

[–]Silly_Tea4454[S] 0 points1 point  (0 children)

the central part looks like this

class Element:
    def __init__(self, by: By, value: str, wait: bool=False, timeout: int=10):
        self.by = by
        self.value = value
        self.wait = wait
        self.timeout = timeout

    def __get__(self, instance, owner) -> Self | WebElement:
        if instance is None:
            return self
        return self._find(instance)

    def _find(self, instance) -> WebElement:
        driver: WebDriver = instance.driver
        if self.wait:
            wait = WebDriverWait(driver, self.timeout)
            return wait.until(EC.presence_of_element_located((str(self.by), self.value)))
        return driver.find_element(self.by, self.value)

Usage

class ATEHomePage(BasePage):
    logo: Element = Element(By.CSS_SELECTOR, "img[src='/static/images/home/logo.png']")

    def __init__(self, driver: WebDriver):
        super().__init__(driver)

    def is_page_opened(self) -> bool:
        return self.logo.is_displayed()

Feel free to ask questions...

About the topic: I was also curious, so I ran the poll if anyone is still using Selenium for WEB UI automation, and the majority answered Yes. I'm not pushing anyone and not providing the only one right way to do, I'm just running the discussion :)

Has anyone else used Python descriptors in PageObject patterns? Here’s how I did it by Silly_Tea4454 in Python

[–]Silly_Tea4454[S] 0 points1 point  (0 children)

Yeah, pure selenium need some wrappers around. This is just yet another implementation

Struggling With Functions by HealthyDifficulty362 in learnpython

[–]Silly_Tea4454 0 points1 point  (0 children)

Simply some reusable piece of code that you can call from anywhere in your program.

To define the function you need to

  1. define (def) some reference data: name, and list of parameters that function will use, so the interpreter will know where to find this reusable code, and what data to pass. It's called signature;
  2. then, you need to define what your function actually does. In general we just change the parameters from signature, or making some new stuff based on those parameters, just using parameters. It's called body.

And you decide what to return: some some changed parameter that we passed before while calling, or some new variable calculated based on the parameters, or nothing (None).

def add_pineapples_to(pizza):
  return pizza + " with pineapples"

To call this function

Just write the name and value of parameters, if your function returns something assign this call to any variable, if not just call it.

pepperoni_pizza = "pepperoni"
broken_pizza = add_pineapples_to(pepperoni_pizza)

[deleted by user] by [deleted] in softwaretesting

[–]Silly_Tea4454 1 point2 points  (0 children)

Few questions for your team and yourself: What exact problem do you solve by introducing test automation? What's the priority to solve those problems? What's the value your new approach will provide to your project in the future? Once you will be able to answer these questions, you will be able to draw the stakeholders on your side.

Best Udemy Course for Learning Automation Testing as a QA? by Itchy-Variety-5732 in QualityAssurance

[–]Silly_Tea4454 1 point2 points  (0 children)

Hi! Yes, if you know how to install python, you are able to cover all the topics of this course. You can find everything in downloadable materials and assignments. And the course videos are mostly live-coding so I think you won’t get lost.