如果我已经有了FindsBy的元素,如何使用Selenium的Wait.Until

时间:2016-03-13 10:42:32

标签: c# selenium findby

我正在使用Wait.Until方法检查我的页面是否已加载或是否仍在加载。 这就是它的样子:

protected IWebElement FindElement(By by, int timeoutInSeconds)
    {
        StackTrace stackTrace = new StackTrace();
        string callingMethod = stackTrace.GetFrame(1).GetMethod().Name;

        string message = "Error finding element in method: " + callingMethod;

        if (timeoutInSeconds > 0)
        {
            try
            {
                WebDriverWait wait = new WebDriverWait(chromeDriver, TimeSpan.FromSeconds(timeoutInSeconds));
                wait.Until(ExpectedConditions.ElementIsVisible(by));
                Thread.Sleep(800);
            }
            catch (Exception)
            {
                Assert(false, message);
                throw new Exception(message);
            }
        }

        return chromeDriver.FindElement(by);
    }

但是现在我们想要改变我们的自动化页面并开始使用FindBy敌人的每个元素,如下所示:

  [FindsBy(How = How.Id, Using = "username")]
    public IWebElement _logInUserName;

但wait.until需要" by"元素。

我看到了这个问题的抽象解决方案,但这对我的情况没有好处。 谁能知道我可以使用的另一种解决方案?

3 个答案:

答案 0 :(得分:2)

有一个ByFactory class in Selenium .NET solution。我采用这种实现来实现你想要的目标:

using OpenQA.Selenium;
using OpenQA.Selenium.Support.PageObjects;
using System;
using System.Globalization;
using System.Linq;
using System.Reflection;

namespace SeleniumPlayground
{
    public static class SeleniumHelper
    {
        public static FindsByAttribute GetFindsByAttributeFromField(Type pageObject, string iwebElementFieldName)
        {

            FieldInfo fi = pageObject.GetField(iwebElementFieldName);

            FindsByAttribute attr = (FindsByAttribute)fi.GetCustomAttributes(typeof(FindsByAttribute), false).FirstOrDefault();

            return attr;
        }

        public static By GeyByFromFindsBy(FindsByAttribute attribute)
        {
            var how = attribute.How;
            var usingValue = attribute.Using;
            switch (how)
            {
                case How.Id:
                    return By.Id(usingValue);
                case How.Name:
                    return By.Name(usingValue);
                case How.TagName:
                    return By.TagName(usingValue);
                case How.ClassName:
                    return By.ClassName(usingValue);
                case How.CssSelector:
                    return By.CssSelector(usingValue);
                case How.LinkText:
                    return By.LinkText(usingValue);
                case How.PartialLinkText:
                    return By.PartialLinkText(usingValue);
                case How.XPath:
                    return By.XPath(usingValue);
                case How.Custom:
                    if (attribute.CustomFinderType == null)
                    {
                        throw new ArgumentException("Cannot use How.Custom without supplying a custom finder type");
                    }

                    if (!attribute.CustomFinderType.IsSubclassOf(typeof(By)))
                    {
                        throw new ArgumentException("Custom finder type must be a descendent of the By class");
                    }

                    ConstructorInfo ctor = attribute.CustomFinderType.GetConstructor(new Type[] { typeof(string) });
                    if (ctor == null)
                    {
                        throw new ArgumentException("Custom finder type must expose a public constructor with a string argument");
                    }

                    By finder = ctor.Invoke(new object[] { usingValue }) as By;
                    return finder;
            }

            throw new ArgumentException(string.Format(CultureInfo.InvariantCulture, "Did not know how to construct How from how {0}, using {1}", how, usingValue));
      }
}

以下是一个示例用法:

public class Page
{
    private IWebDriver driver;

    [FindsBy(How = How.Id, Using = "content")]
    public IWebElement ele;

    public Page(IWebDriver _driver)
    {
        this.driver = _driver;
    }
}

使用如下:

Page page = PageFactory.InitElements<Page>(driver);

FindsByAttribute findsBy = SeleniumHelper.GetFindsByAttributeFromField(typeof(Page), "ele");

By by = SeleniumHelper.GeyByFromFindsBy(findsBy);

答案 1 :(得分:1)

我找到了办法:)

        public static IWebElement FindElement( IWebElement element, int timeoutInSeconds)
    {
        if (timeoutInSeconds > 0)
        {
            var wait = new WebDriverWait(chromeDriver, TimeSpan.FromSeconds(timeoutInSeconds));
            return wait.Until(drv => element);
        }
        return element;
    }

答案 2 :(得分:1)

使用硒进行测试时遇到了同样的问题。所以我们在selenium之上创建了一个迷你框架,它一直在努力(无论你想用硒做什么)。或者您可以提供自定义的前置或后置条件。

https://github.com/LiquidThinking/Xenon

设置非常简单,所有信息都可以在github上获得,另外还有Screen对象,可以帮助重用代码。

例如

MobID

所以在这个例子中,我们添加了一个预先等待条件,说“在进入google.co.uk之前确保当前页面包含页面源中的”google“。这显然是不正确的方法,但它解释如何使用等前或等待条件。

如果您没有指定任何等待条件,那么对于某些操作,则存在默认的等待操作。例如https://github.com/LiquidThinking/Xenon/blob/master/Xenon/BaseXenonTest.cs#L72 看看我们如何检查customPreWait是否可用于“Click”,如果没有,那么我们在执行“实际点击操作”之前添加了自定义预等待以检查页面上是否存在css选择器。

希望它会帮助你,它是nuget或者只是使用你想要的代码。它是在麻省理工学院的许可下。