一段时间后,我正在使用WebDriverWait来获取WebElement的值,但是如果它没有变化,我不希望它失败,只需获取当前值并继续执行即可。

我正在Web中运行一个带有“进程已完成”标签的进程,该标签用于检查进程是否完成。在同一屏幕上,我需要阅读该过程的“经过时间”,以报告运行该过程花费了多少时间。
问题是,即使出现了“进程完成”标签,也有一个后端进程在运行,并且时间得到更新。我不知道此“后端更新”将花费多少时间,而且我不知道它是否可以在愉快的运行中出现在提到的标签之前,目前,从我的测试来看,它需要10到40秒(60到确定)。

我们有一个用于此类内容的Waits类,但是我们没有用于此文本更改验证的方法,因此我想到了:

private static WebDriverWait _customWait(int value) => new WebDriverWait(
    clock,
    Driver.Instance,
    TimeSpan.FromSeconds(value),
    TimeSpan.FromMilliseconds(Settings.Timeouts.SleepIntervalInMillis));

public static void WaitForTextElementToChange(Func<IWebDriver, IWebElement> elementFinder, IWebDriver driver, int time)
{
    string oldValue = elementFinder.Invoke(driver).Read();
    _customWait(time).Until(drv =>
    {
        try
        {
            return !elementFinder.Invoke(driver).Read().Contains(oldValue);
        }
        catch (NotFoundException)
        {
            return true;
        }
        catch (StaleElementReferenceException)
        {
            return true;
        }
    });
}


这可行。我之所以这样说是因为我还没有完全理解该Until方法背后的语法和逻辑,我知道它提供了一个WebDriverTimeoutException,我将其保留为框架的另一种方法。

因此,如果值更改了,它就会消失并保持正常运行,但是在这种特殊情况下,如果它没有更改,则不需要它引发该异常,因此可以在try/catch中调用它。

Waits.WaitForProcessToFinish(drv => processCompleteLabel); //<- context code
try
{
    //If value changes before 60 secs everything is fine
    Waits.WaitForTextElementToChange(drv => timeElement, someDriverObject, 60);
    //60 is a hardcoded int value just for testing
}
catch (WebDriverTimeoutException)
{
    //But if it doesn't change just do nothing
}
string timeElapsed = timeElement.Read(); //<- context code


我的问题是,这样下去可以吗?
您会怎么做?

最佳答案

根据我在源代码中看到的内容,我认为Until的工作方式尚无解决方法。

直到循环返回布尔或对象或发生超时之前,直到方法执行循环中传递给它的方法。

public virtual TResult Until<TResult>(Func<T, TResult> condition)
{
    if (condition == null)
    {
        throw new ArgumentNullException("condition", "condition cannot be null");
    }

    var resultType = typeof(TResult);
    if ((resultType.IsValueType && resultType != typeof(bool)) || !typeof(object).IsAssignableFrom(resultType))
    {
        throw new ArgumentException("Can only wait on an object or boolean response, tried to use type: " + resultType.ToString(), "condition");
    }

    Exception lastException = null;
    var endTime = this.clock.LaterBy(this.timeout);
    while (true)
    {
        try
        {
            var result = condition(this.input);
            if (resultType == typeof(bool))
            {
                var boolResult = result as bool?;
                if (boolResult.HasValue && boolResult.Value)
                {
                    return result;
                }
            }
            else
            {
                if (result != null)
                {
                    return result;
                }
            }
        }
        catch (Exception ex)
        {
            if (!this.IsIgnoredException(ex))
            {
                throw;
            }

            lastException = ex;
        }

        // Check the timeout after evaluating the function to ensure conditions
        // with a zero timeout can succeed.
        if (!this.clock.IsNowBefore(endTime))
        {
            string timeoutMessage = string.Format(CultureInfo.InvariantCulture, "Timed out after {0} seconds", this.timeout.TotalSeconds);
            if (!string.IsNullOrEmpty(this.message))
            {
                timeoutMessage += ": " + this.message;
            }

            this.ThrowTimeoutException(timeoutMessage, lastException);
        }

        Thread.Sleep(this.sleepInterval);
    }
}


您正在做什么,但是我建议您使用自己的超时循环而不使用Wait.Until(),因为它的核心功能是在出现问题时引发异常。

09-10 03:07
查看更多