用Python封装Selenium的“期望条件”
我正在尝试创建一个自己的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 个回答
你代码的问题在于你把“By”这个数据类型转换成了字符串。
一个简单的方法是像下面这样传递它,不要加引号:
self.waitForElement("elementName", "element_to_be_clickable", By.NAME, "test")
你需要做的唯一额外的事情是,在你调用上面这个方法的Python模块中添加下面的导入语句,以便使用By:
from selenium.webdriver.common.by import By
你可以这样开始:
首先创建一个主要的 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);
我正在使用的框架里也做了类似的事情
最后,我通过问了这个问题,终于解决了这个问题。为了实现我想要的功能,上面提到的方法看起来是这样的:
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")