首页 > 解决方案 > 如果 Element 不可见,则继续方法

问题描述

我正在使用 C#/Selenium 测试 UI,并且有一个数据输入部分,然后是一个结果窗口。要么返回结果,要么不返回结果。我正在测试这两种情况

我为此测试创建了一种方法,如下所示。这可用于测试元素是否存在的是/否场景......

    public bool HasResults()
    {

            IList<IWebElement> yesResultElement = _driver.FindElements(yesResults);

            if (yesResultElement.Count > 0)
            {
                return true;
            }


            IList<IWebElement> noResultElement = _driver.FindElements(noResults);
        
            if (noResultElement.Count > 0)
            {
                return false;
            }

        throw new Exception("Could not determine if there were results");

    }

问题是,当我测试“noResultElement”时,此方法会挂起并超时,因为它找不到“yesResultElement”。

我尝试在第一个 IF 语句周围添加一个 try/catch

    public bool HasResults()
    {
        try
        {

            IList<IWebElement> yesResultElement = _driver.FindElements(yesResults);

            if (yesResultElement.Count > 0)
            {
                return true;
            }
        }
        catch
        {
            Console.WriteLine("element does not exist");
        }

        IList<IWebElement> noResultElement = _driver.FindElements(noResults);
        
        if (noResultElement.Count > 0){
            return false;
        }

        throw new Exception("Could not determine if there were results");

    }

这解决了问题,但它也将 20 秒的测试变成了 > 1 分钟(由于测试文件中指定了隐式等待)

除了将其拆分为 2 种方法之外,还有更好的方法来处理这个问题吗?如果 yesResultElement 不存在,请忽略该 IF 语句并转到下一个,这就是我想要的。

测试看起来像这样

[TestMethod]

    public void NoRecordsFoundTest()
    {
        // Tests whether no records are found when that is the expected outcome
        var searchPage = new SearchPage(driver);
        var firstTest = testData.First();
        searchPage.EnterSearchInfo(firstTest);
        var result = searchPage.HasResults();
        try
        {
            result.Should().BeFalse();
            log.Debug("The No Records Found Test Passed");
        }
        catch (AssertFailedException ex)
        {
            log.Debug("The No Records Found Test Failed",ex);
            Assert.Fail();
        }
    }


    [TestMethod]

    public void RecordsFoundTest()
    {

        // Tests whether records are found when that is the expected outcome

        var searchPage = new SearchPage(driver);
        var firstTest = testData.Skip(1).First();
        searchPage.EnterSearchInfo(firstTest);
        var result = searchPage.HasResults();
        try
        {
            result.Should().BeTrue();
            log.Debug("The Records Found Test Passed");
        }
        catch (AssertFailedException ex)
        {
            log.Debug("The Records Found Test Failed", ex);
            Assert.Fail();
        }
    }

不确定其相关但测试数据是从 JSON 文件加载并传递到 EnterSearchInfo() 方法。

此外,UI 中的一个小故障是即使返回了结果,noResultElement 也会在一瞬间出现,然后消失。

标签: c#seleniumelement

解决方案


您可以暂时将隐式等待超时设置为某个较小的值,反复尝试查找您的元素,等待至少找到一个组(使用OpenQA.Selenium.Support.UI.WebDriverWait),然后根据找到的组返回一个布尔值。

像这样的扩展方法可能会有所帮助:

public static class WebDriverExtensions
{
    /// <summary>
    /// Executes the specified `action` with `ImplicitWait` set to the specified `timeout`.
    /// </summary>
    /// <typeparam name="T">The action return type.</typeparam>
    /// <param name="b">The WebDriver instance.</param>
    /// <param name="timeout">
    /// The duration that WebDriver should implicitly wait until it gives up on trying to
    /// find an element.
    /// </param>
    /// <param name="action">
    /// The action to execute with the special ImplicitWait setting.
    /// </param>
    /// <returns>The action result.</returns>
    public static T WithImplicitWait<T>(this ChromeDriver b, TimeSpan timeout, Func<T> action)
    {
        ITimeouts timeouts = b.Manage().Timeouts();
        TimeSpan oldImplicitWait = timeouts.ImplicitWait;
        try
        {
            timeouts.ImplicitWait = timeout;
            return action();
        }
        finally
        {
            timeouts.ImplicitWait = oldImplicitWait;
        }
    }
}

然后你会像这样使用它:

public bool HasResults()
{
    var wait = new WebDriverWait(_driver, TimeSpan.FromSeconds(10))
    {
        Message = "Could not find neither 'yes' nor 'no' results."
    };
    var implicitTimeout = TimeSpan.FromMilliseconds(200);
    string found =_driver.WithImplicitWait(implicitTimeout, () => wait.Until(b =>
    {
        IList<IWebElement> yesResultElement = _driver.FindElements(yesResults);
        IList<IWebElement> noResultElement = _driver.FindElements(noResults);
        if (yesResultElement.Count == 0 && noResultElement.Count == 0)
        {
            return null;
        }

        if (yesResultElement.Count > 0 && noResultElement.Count > 0)
        {
            return "both";
        }

        return yesResultElement.Count > 0 ? "yes" : "no";
    }));
    bool result = found switch
    {
        "yes" => true,
        "no" => false,
        _ => throw new Exception("Could not determine if there were results")
    };
    return result;
}

WebDriverWait.Until将重复调用您的回调,直到它返回一个非空值,因此我们null在没有找到任何组时返回。它将在(在这种情况下)10 秒后放弃并失败并显示指定的错误消息。


推荐阅读