【发布时间】:2012-01-14 06:00:15
【问题描述】:
为了解释我的问题,我给出了一个小场景:
假设我有一个登录页面。
public class LoginPage
{
[FindsBy(How = How.Id, Using = "SomeReallyLongIdBecauseOfAspNetControlsAndPanels_username"]
public IWebElement UsernameField { get; set; }
[FindsBy(How = How.Id, Using = "SomeReallyLongIdBecauseOfAspNetControlsAndPanels_password"]
public IWebElement PasswordField { get; set; }
[FindsBy(How = How.Id, Using = "submitButtonId")]
public IWebElement SubmitButton { get; set; }
private readonly IWebDriver driver;
public LoginPage(IWebDriver driver)
{
this.driver = driver;
if(!driver.Url.Contains("Login.aspx"))
{
throw new NotFoundException("This is not the login page.");
}
PageFactory.InitElements(driver, this);
}
public HomePage Login(Credentials cred)
{
UsernameField.sendKeys(cred.Username);
PasswordField.SendKeys(cred.Password);
SubmitButton.Click();
return new HomePage(driver);
}
}
[TestFixture]
public class Test : TestBase
{
private IWebDriver driver;
[SetUp]
public void SetUp()
{
driver = StartDriver(); // some function which returns my driver in a wrapped event or something so I can log everything it does.
}
[Test]
public void Test()
{
new LoginPage(driver)
.Login(new Credentials
{ Username = "username",
Password = "password" })
.SomeHomePageFunction()
}
最终,我知道页面配置会发生变化,id 将基本保持不变,但我的项目正在迅速发生变化。我知道 xPath 是另一种选择,但由于页面是基于某些标准生成的,这仍然会变得很痛苦,因为路径并不总是相同。
使用上面的当前代码,页面被加载,PageFactory 通过页面构造函数初始化元素。都很棒。这是我目前使用的。
目前,如果某些东西并不总是在页面上生成,直到某个步骤。我通常会这样做:
private const string ThisIsTheUserNameFieldId = "usernamefield";
然后使用以下命令打开 webdriver:
// Navigate to login page
// code here
// Enter in credentials
driver.FindElement(By.Id(ThisIsTheUserNameFieldId)).SendKeys(cred.Username);
结构不如 PageFactory,但它肯定是我无法解决的要求。
我最近遇到了一些与 C#.Net 一起使用的 jQuery 选择器代码,它扩展了 RemoteWebDriver 的功能,我可以使用 jQuery 选择器在页面上找到我的元素。
Selenium jQuery for C#.Net (Including Source)
// So I can do things like this:
driver.FindElement(By.jQuery("a").Find(":contains('Home')").Next())
有谁知道我可以如何扩展 Selenium WebDriver 中的 [FindsBy] 属性,以便可以使用类似以下的内容(伪代码)?
[FindsBy(How = How.jQuery, Using = "div[id$='txtUserName']")]
public IWebElement UsernameField { get; set; }
【问题讨论】:
-
请记住,XPath 非常强大,您可以轻松地将 div[id$='txtUserName'] 转换为 //div[ends-with(@id, 'txtUserName')]
-
我可以发誓我曾尝试过这种方法。我做了一个快速的单元测试。 OpenQA.Selenium.InvalidSelectorException:给定的选择器 //input[ends-with(@id, 'txtUserName')] 无效或不会生成 WebElement。发生以下错误:[InvalidSelectorError] 无法找到具有 xpath 表达式的元素 //input[ends-with(@id, 'txtUserName')] 因为以下错误:[Exception..."The expression is not a法律表达。”代码:“51”nsresult:“0x805b0033(NS_ERROR_DOM_INVALID_EXPRESSION_ERR)”位置:“resource://fxdriver/modules/atoms.js 行:2394”]
-
很遗憾,因为我在几个页面上有几个重要的网络元素,这些元素在网站使用所涉及的每个步骤的每个过程中都被大量使用。我还尝试使用 Firefox 插件来帮助识别 xPath 表达式,甚至那些似乎被 Selenium 无效的表达式。但是我确实认为该插件已经很老了,但它仍然存在。在它工作之前它很混乱,这很好,但是我似乎总是陷入 XPath 的这个问题。
-
真可惜,我本来希望 WebDriver 能够处理 XPath 函数...我想您需要像我在下面发布的那样。
-
原来它是 xPath 2 的一部分,新的 Selenium 2 WebDriver 甚至都不支持它......这太糟糕了。
标签: jquery-selectors attributes webdriver selenium-webdriver