Element Present 方法是否损坏了

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

我更新了我的框架,我用于“元素是否存在”的方法坏了,我不知道为什么?当找到该元素时,没有问题并且返回 true。当未找到该元素时,它不会返回 false,而是抛出以下错误并使测试用例失败。

我在这里缺少什么想法吗?

OpenQA.Selenium.NoSuchElementException:'没有这样的元素:无法定位元素:{“method”:“xpath”,“selector”:“//my[@id='xpath']”}

元素定位器

public const string eleVal = "//my[@id='xpath']";

public IWebElement _eleVal { get { return Browser.Driver.FindElement(By.XPath(eleVal )); } }

获取状态的方法。当未找到该元素时,它会失败。

public bool GetValue()
{
    bool ele = Driver.IsElementPresent(_eleVal);

    if (ele)
    {
        return true;
    }
    else
    {
        return false;
    }
}

一直有效的方法

public static bool IsElementPresent(IWebElement element)
{
    bool result;

    try
    {
        result = element.Displayed;
    }
    catch (NoSuchElementException)
    {
        return false;
    }
    catch (StaleElementReferenceException)
    {
        return false;
    }
    catch (WebDriverException)
    {
        return false;
    }

    return result;
}
c# selenium-webdriver
1个回答
0
投票

问题是

GetValue()
_eleVal
内部被评估,这就是
.FindElement()
调用失败的地方。那是在你的
try-catch
之外。如果您希望您的
try-catch
真正捕获该异常,您需要在其中使用
.FindElement()
。我会用不同的方式来写这一切。

  1. 不要将定位器仅存储为 XPath 的字符串组件,而是将其存储为

    By
    定位器。这使您能够在一处更改定位器类型和定位器字符串。它还允许您将
    By
    传递给方法等。

    string eleVal = "//my[@id='xpath']";
    

    成为

    By elementLocator = By.XPath("//my[@id='xpath']");
    
  2. 这看起来可能是页面对象的一部分?页面对象设计的核心是向用户隐藏页面的详细信息,只向他们提供一个漂亮、干净的 API 来调用给定页面。这意味着定位器应该是

    private

    public const string eleVal = "//my[@id='xpath']";
    

    成为

    private readonly By elementLocator = By.XPath("//my[@id='xpath']");
    
  3. 不要将状态存储在页面对象(或元素定位器所在的任何类)中。这很容易导致

    StaleElementExceptions
    等问题。它还可以阻止您并行运行测试等。在这种情况下存储状态是将
    IWebElement
    存储在类字段中。相反,只需存储定位器,当您需要查找元素时,请使用
    .FindElement()
    WebDriverWait
    。删除下面的行

    public IWebElement _eleVal { get { return Browser.Driver.FindElement(By.XPath(eleVal )); } }
    

    然后将定位器从 #1 传递到方法中以查找该元素等。

  4. GetValue()
    可以大大简化。它还应该接受
    By
    定位器参数。整个方法可以简化为

    public bool GetValue(By locator)
    {
        return Driver.IsElementPresent(locator);
    }
    

    话虽如此,我不知道为什么

    GetValue()
    存在。它并不像名称所暗示的那样“获取值”。它本身也不做任何事情...
    IsElementPresent()
    完成所有工作,所以我会删除
    GetValue()
    除非还有您未包含的其他代码。

  5. 结合之前的几个建议,我会重写

    IsElementPresent()
    以采用
    By
    定位器而不是
    IWebElement
    。这将允许您在需要时抓住元素,避免多次出现诸如
    StaleElementExceptions
    等问题。

  6. 您的方法

    IsElementPresent()
    正在检查元素是否可见,而不是存在。 Present 意味着该元素位于 DOM 中,而不是它可见或可点击。
    .Displayed
    检查该元素是否可见,这就是您要返回的内容。我会将此方法重命名为
    IsElementVisible()
    。我还写了一个
    IsElementPresent()
    方法,以防你需要。

考虑到所有这些,我将如何重写这一切。

  1. 定位器为
    private
    readonly
    By
  2. 不再需要
  3. GetValue()
    。如果您需要
    GetValue()
    的等价物,请致电
    IsElementVisible(locator)
  4. 简化并将
    IsElementPresent()
    重命名为
    IsElementVisible(locator)
    以匹配其功能,并采用
    By
    定位器。
  5. 编写
    IsElementPresent(locator)
    以匹配方法名称的内容并采用
    By
    定位器。

完整更新的代码

private readonly By elementLocator = By.XPath("//my[@id='xpath']");

...

public bool IsElementPresent(By locator)
{
    return Driver.FindElements(locator).Any();
}

public bool IsElementVisible(By locator)
{
    var e = Driver.FindElements(locator);
    if (e.Count == 0)
    {
        return false;
    }

    try
    {
        return e.ElementAt(0).Displayed;
    }
    catch (StaleElementReferenceException)
    {
        return false;
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.