如何编写一个适用于Web实用程序类中所有函数的等待装饰器?

问题描述 投票:0回答:1

这是我的 WebUtils 类:

from selenium.webdriver.support.wait import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC


def wait_for_element(func):
    def wrapper(*args, **kwargs):
        loctype, locvalue = args[-1]
        driver = args[0]
        wait = WebDriverWait(driver, 10)
        element = wait.until(EC.element_to_be_clickable((loctype, locvalue)))
        element.click()
        return func(driver, *args, **kwargs)
    return wrapper




class WebUtils:

    @wait_for_element
    def sendKeys(self, driver, string, element):
        loctype, locvalue = element
        print(loctype, locvalue)
        driver.find_element(loctype, locvalue).send_keys(string)

    @wait_for_element
    def clickElement(self, driver, element):
        loctype, locvalue = element
        print(loctype, locvalue)
        driver.find_element(loctype, locvalue).click()

此外,PFA 我的文件/文件夹树的图像。我的目标是编写一个装饰器来处理显式等待所有元素。 (我知道这可以通过修改函数轻松完成,但我想使用装饰器来完成,因为这不是 python 中的装饰器的用途吗?)。 我收到此错误:

FAILED test/test_register.py::TestReg::test_launch_url[test_case1] - AttributeError: 'WebUtils' object has no attribute 'find_element'      
FAILED test/test_register.py::TestReg::test_launch_url[test_case2] - AttributeError: 'WebUtils' object has no attribute 'find_element' 

我什至尝试将装饰器放在类中。这也没有帮助

我什至无法理解为什么这是一个

find_element
WebUtils
类的属性的问题。有人可以帮我解决这个问题吗?这是文件夹树:

python selenium-webdriver
1个回答
0
投票

您可以像这样用

WebDriverWait
expected_conditions
包装方法,以简化脚本并自动等待:

import sys
from selenium import webdriver
from selenium.webdriver.chrome.service import Service
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.support.ui import WebDriverWait
from unittest import TestCase

class RefinedRawSelenium(TestCase):
    def setUp(self):
        self.driver = None
        options = webdriver.ChromeOptions()
        options.add_argument("--disable-notifications")
        if "linux" in sys.platform:
            options.add_argument("--headless=new")
        options.add_experimental_option(
            "excludeSwitches", ["enable-automation", "enable-logging"],
        )
        prefs = {
            "credentials_enable_service": False,
            "profile.password_manager_enabled": False,
        }
        options.add_experimental_option("prefs", prefs)
        service = Service(service_args=["--disable-build-check"])
        self.driver = webdriver.Chrome(options=options, service=service)

    def tearDown(self):
        if self.driver:
            try:
                if self.driver.service.process:
                    self.driver.quit()
            except Exception:
                pass

    def wait_for_element_visible(
        self, selector, by="css selector", timeout=10
    ):
        try:
            return WebDriverWait(self.driver, timeout).until(
                EC.visibility_of_element_located((by, selector))
            )
        except Exception:
            raise Exception(
                "Element {%s} was not visible after %s seconds!"
                % (selector, timeout)
            )

    def wait_for_element_clickable(
        self, selector, by="css selector", timeout=10
    ):
        try:
            return WebDriverWait(self.driver, timeout).until(
                EC.element_to_be_clickable((by, selector))
            )
        except Exception:
            raise Exception(
                "Element {%s} was not visible/clickable after %s seconds!"
                % (selector, timeout)
            )

    def wait_for_element_not_visible(
        self, selector, by="css selector", timeout=10
    ):
        try:
            return WebDriverWait(self.driver, timeout).until(
                EC.invisibility_of_element((by, selector))
            )
        except Exception:
            raise Exception(
                "Element {%s} was still visible after %s seconds!"
                % (selector, timeout)
            )

    def open(self, url):
        self.driver.get(url)

    def click(self, selector, by="css selector", timeout=7):
        el = self.wait_for_element_clickable(selector, by=by, timeout=timeout)
        el.click()

    def type(self, selector, text, by="css selector", timeout=10):
        el = self.wait_for_element_clickable(selector, by=by, timeout=timeout)
        el.clear()
        if not text.endswith("\n"):
            el.send_keys(text)
        else:
            el.send_keys(text[:-1])
            el.submit()

    def assert_element(self, selector, by="css selector", timeout=7):
        self.wait_for_element_visible(selector, by=by, timeout=timeout)

    def assert_text(self, text, selector="html", by="css selector", timeout=7):
        el = self.wait_for_element_visible(selector, by=by, timeout=timeout)
        self.assertIn(text, el.text)

    def assert_exact_text(self, text, selector, by="css selector", timeout=7):
        el = self.wait_for_element_visible(selector, by=by, timeout=timeout)
        self.assertEqual(text, el.text)

    def assert_element_not_visible(
        self, selector, by="css selector", timeout=7
    ):
        self.wait_for_element_not_visible(selector, by=by, timeout=timeout)

    def test_add_item_to_cart(self):
        self.open("https://www.saucedemo.com")
        self.type("#user-name", "standard_user")
        self.type("#password", "secret_sauce\n")
        self.assert_element("div.inventory_list")
        self.assert_text("Products", "span.title")
        self.click('button[name*="backpack"]')
        self.click("#shopping_cart_container a")
        self.assert_exact_text("Your Cart", "span.title")
        self.assert_text("Backpack", "div.cart_item")
        self.click("#remove-sauce-labs-backpack")
        self.assert_element_not_visible("div.cart_item")
        self.click("#react-burger-menu-btn")
        self.click("a#logout_sidebar_link")
        self.assert_element("input#login-button")

# When run with "python" instead of "pytest" or "python -m unittest"
if __name__ == "__main__":
    from unittest import main
    main()

SeleniumConf 2023(YouTube Playlist)的 Python 演示中对此进行了描述,作为构建使用简化脚本并具有自动等待功能的 Python Selenium 框架的最佳方式。

© www.soinside.com 2019 - 2024. All rights reserved.