用Python封装Selenium的“期望条件”

4 投票
3 回答
3881 浏览
提问于 2025-04-20 15:26

我正在尝试创建一个自己的Selenium类,里面有一些自定义的功能,这样在编写测试脚本时会更直观,也在某些情况下更稳健,至少对我来说是这样的。现在我正在做的一个任务是把所有Selenium的预期条件(可以在这里找到)封装起来,最终我希望能有一个看起来像这样的单一函数:

def waitForElement(self, elementName, expectedCondition, searchBy)

其中:

elementName - 我想要查找的元素的名称。这个可以是id、name、xpath、css等。

expectedCondition - 这里设置Selenium的预期条件。可以是:element_to_be_clickable、visibility_of_element_located等。

上面的函数内部实现了标准的Selenium WebDriverWait,具体如下:

try:
    if expectedCondition == "element_to_be_clickable":
        element = WebDriverWait(self.driver, defaultWait).until(EC.element_to_be_clickable((searchBy, elementName)))
    elif expectedCondition == "visibility_of_element_located":
        element = WebDriverWait(self.driver, defaultWait).until(EC.visibility_of_element_located((searchBy, elementName)))

一切都很好,但我在传递searchBy作为参数时遇到了一些麻烦。提醒一下,searchBy可以是以下之一:

By.ID
By.NAME
By.CLASS_NAME
...

当我从主代码调用这个封装函数时,我是用下面这一行:

self.waitForElement("elementName", "element_to_be_clickable", "By.NAME", "test")

所以所有参数都是以字符串的形式传递,这对其他部分都没问题,除了searchBy

所以我的问题是:我该如何将By.X部分作为参数传递给我的函数?希望我能清楚地描述我的情况。如果没有,我会很乐意进一步解释。

3 个回答

0

你代码的问题在于你把“By”这个数据类型转换成了字符串。

一个简单的方法是像下面这样传递它,不要加引号:

self.waitForElement("elementName", "element_to_be_clickable", By.NAME, "test")

你需要做的唯一额外的事情是,在你调用上面这个方法的Python模块中添加下面的导入语句,以便使用By:

from selenium.webdriver.common.by import By

0

你可以这样开始:

首先创建一个主要的 findElement 方法,这个方法需要接受一个 By 实例:

WebElement findElement(By by) {
        try {
            return driver.findElement(by);
        } catch (NoSuchElementException e) {
            logException("ERROR: Could not find - '" + by + "' on page " + driver.getCurrentUrl());
            throw e;
        }

然后创建一个等待方法,这个方法会使用刚才的 findElement 方法:

WebElement findElementAndWaitElementToPresent(By by, int timeoutInSeconds) {
        try {
            WebDriverWait wait = new WebDriverWait(driver, timeoutInSeconds);
            wait.until(ExpectedConditions.presenceOfElementLocated(by));
            return findElement(by);
        } catch (TimeoutException e) {
            logException("ERROR: Element is not present: " + by + " on page " + driver.getCurrentUrl());
            throw e;
        }
    }

接着把 By 实例传递给 findElementAndWaitElementToPresent 方法:

findElementAndWaitElementToPresent(By.xpath("//your_xpath"), 10);

或者

findElementAndWaitElementToPresent(By.name("name"), 10);

我正在使用的框架里也做了类似的事情

1

最后,我通过问了这个问题,终于解决了这个问题。为了实现我想要的功能,上面提到的方法看起来是这样的:

def waitForElement(self, elementName, expectedCondition, searchBy):
    try:
        if expectedCondition == "element_to_be_clickable":
            element = WebDriverWait(self.driver, self.defaultWait).until(EC.element_to_be_clickable((getattr(By, searchBy), elementName)))
        elif expectedCondition == "visibility_of_element_located":
            element = WebDriverWait(self.driver, self.defaultWait).until(EC.visibility_of_element_located((getattr(By, searchBy), elementName)))

        . . . 

所以可以这样调用:

self.waitForElement("elementName", "element_to_be_clickable", "NAME")

撰写回答