简体   繁体   中英

Continue in method if Element is not visible

I am testing a UI with C#/Selenium and there is a data entry section, followed by a results window. There are either results returned, or no results returned. I am testing both scenarios

I created a method for this testing as below. This can be used to either test Yes/No scenarios whether an element exists or not...

    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");

    }

The problem is, when I am testing for 'noResultElement', this method is getting hung up and timing out because it can't find the 'yesResultElement'.

I tried adding a try/catch around the first IF statement

    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");

    }

That resolves the issue, but it also turns a 20 second test into > 1 min (due to Implicit Wait specified in Test file)

Aside from splitting this into 2 methods, is there a better way to handle this? if yesResultElement is not present, ignore that IF statement and move onto the next one, is what I want.

The Tests look like this

[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();
        }
    }

Not sure its relevant but test data is loaded from JSON file and passed into EnterSearchInfo() method.

Also, one glitch in the UI is even if results are returned, for a split second the noResultElement appears, and then goes away.

You can temporarily set the implicit wait timeout to some small value, repeatedly try to find your elements, waiting until at least one group is found (using OpenQA.Selenium.Support.UI.WebDriverWait ), then return a boolean value depending on which group was found.

An extension method like this may be helpful:

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;
        }
    }
}

Then you would use it like this:

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 will repeatedly call your callback until it returns a non-null value, therefore we return null when neither group is found. It will give up after (in this case) 10 seconds and fail with the specified error message.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM