提问者:小点点

扩展方法可以使用非静态字段吗?


我不确定这个序言是否必要(全部或根本),但我认为它传达了我需要在静态扩展方法中使用非静态字段的用例。

我有一个使用Selenium/C#/NUnit实现的测试套件。

我曾经使用PageFactory来定义我的页面元素。PageFactory已被弃用,因此切换到将我的元素定义为IWebElements似乎是合乎逻辑的:

主页. cs…

IWebElement UsernameTextBox = driver.FindElement(By.Id("username"));
IWebElement PasswordTextBox = driver.FindElement(By.Id("password"));
IWebElement LoginButton = driver.FindElement(By.Id("login"));

这种方法的问题是,在运行任何测试之前,会逐行读取此文件,并且在我的测试尝试使用它们之前会查询所有这些元素的DOM。当然,他们会抛出元素未找到异常,因为在查询元素时,还没有运行测试,这意味着我们甚至不在主页上与它们交互。

为了解决这个问题,我将元素的类型更改为By:

主页. cs…

By UsernameTextBox = By.Id("username");
By PasswordTextBox = By.Id("password");
By LoginButton = By.Id("login");

这允许我定义元素,然后在正确的时间查询DOM。太好了,问题解决了。除了,现在我有另一个问题。我喜欢能够将方法从IWebElements中链接出来,用于易读性目的:

LoginButton.Click();

但是'By'类型不包含IWebElement所包含的方法。所以下一个合乎逻辑的步骤是:创建一个扩展方法。

public static class ByExtensionMethods {
    public static void Click(this By elementLocator) {
        driver.FindElement(elementLocator);
    }
}

太好了,问题解决了。除了,现在我有另一个问题。我的测试套件不能使用静态IWebDriver,因为我想并行执行我的测试。可悲的是,扩展方法方法要求驱动程序是静态的。

因此,除非我可以以某种方式在扩展方法中使用我的非静态IWebDriver,否则我似乎无法实现将方法从“By”元素中链接出来的目标……


共3个答案

匿名用户

我还必须找到页面工厂的替代品。幸运的是,C#具有称为表达式主体成员的方便功能。

对于您的主页,元素将是:

IWebElement UsernameTextBox => driver.FindElement(By.Id("username"));
IWebElement PasswordTextBox => driver.FindElement(By.Id("password"));
IWebElement LoginButton => driver.FindElement(By.Id("login"));

Selenium将在执行期间搜索这些元素,而不是在开始时,因此不会抛出异常。

匿名用户

扩展方法可以使用非静态字段吗?

没有。

因此,除非我可以以某种方式在扩展方法中使用我的非静态IWebDriver,否则我似乎无法实现将方法从“By”元素中链接出来的目标……

只需将驱动程序对象传递给扩展方法并使用它。

示例:

public static class ByExtensionMethods {
    public static void Click(this By elementLocator, IWebDriver driver) {
        driver.FindElement(elementLocator);
    }
}

匿名用户

我回答这个问题也是为了扩展已经给出的答案(我提到了从“通过”类型中链接方法)。

因此,为此,我发现我应该使扩展方法具有“By”类型,并返回与我使用的By引用相同的…

    public static By Click(this By elementLocator, IWebDriver driver) 
    {
        driver.FindElement(elementLocator).Click();
        return elementLocator;
    }

    public static By Click2(this By elementLocator, IWebDriver driver) 
    {
        driver.FindElement(elementLocator).Click();
        return elementLocator;
    }

这使我能够执行以下操作:

            HomePage homePage = new HomePage(_driver);

            homePage
            .PrivacyPolicyLink
            .Click(_driver)
            .Click2(_driver);

并不是说我会两次单击同样的事情,这只是一个快速的例子。现在通过不在每一个扩展方法调用中引用驱动程序来优雅地做到这一点……