我不确定此序言是否必要(全部或全部),但我认为它传达了我的用例,需要在静态扩展方法内使用非静态字段。
我有一个使用Selenium / C#/ NUnit实现的测试套件。
我曾经使用PageFactory定义页面元素。 PageFactory已过时,因此切换到将我的元素定义为IWebElements似乎合乎逻辑:
HomePage.cs ...
IWebElement UsernameTextBox = driver.FindElement(By.Id("username"));
IWebElement PasswordTextBox = driver.FindElement(By.Id("password"));
IWebElement LoginButton = driver.FindElement(By.Id("login"));
这种方法的麻烦在于,在运行任何测试之前,都会逐行读取此文件,并且在我的测试尝试使用它们之前,正在为所有这些元素查询DOM。他们当然会抛出ElementNotFound异常-在查询元素时,尚未进行任何测试,这意味着我们甚至不在主页上与它们进行交互。
为了解决这个问题,我将元素的类型更改为By:
HomePage.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'元素之外的目标...
所以除非我能以某种方式在扩展方法中使用我的非静态IWebDriver,否则看来我无法实现将方法链接到'By'元素之外的目标...
只需将驱动程序对象传递给扩展方法并使用它。
示例:
public static class ByExtensionMethods {
public static void Click(this By elementLocator, IWebDriver driver) {
driver.FindElement(elementLocator);
}
}