6

我想编写自己的定位器来访问元素。WebDriver 的 API 目前提供了 8 个定位器,允许通过 id、名称属性、标签名称、完整或部分链接文本、XPath、类名和 css 选择器检索元素。但是,这些默认定位器现在对我来说还不够,因为我必须通过新属性访问元素。让我举一个例子,这样你就可以理解我在这里真正想要什么。

示例: 选择您的用户名:

现在我想编写一个代码,以便我可以使用 myLocator 定位器访问用户名按钮,例如:

*driver.findElement(By.myLocator("username")).*

如果有人能给我们一些好主意,我将如何重写 BY 类以添加我自己的定位器,这将非常有帮助。

预先感谢您的帮助。

4

5 回答 5

6

使用 c#

using OpenQA.Selenium;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

public class ImageBy : By
{
    public ImageBy(string imageByString)
    {
        FindElementMethod = (ISearchContext context) =>
        {
            IWebElement mockElement = context.FindElement(By.XPath("//img[@src='" + imageByString + "']"));
            return mockElement;
        };

        FindElementsMethod = (ISearchContext context) =>
        {
            ReadOnlyCollection<IWebElement> mockElements = context.FindElements(By.XPath("//img[@src='" + imageByString + "']"));
            return mockElements;
        };
    }
}

用法如下

[FindsBy(How = How.Custom, Using = @"/path/to/img", CustomFinderType = typeof(ImageBy) )]
private IWebElement MenuStartButton = null;

使用 Java

import java.util.List;

import org.openqa.selenium.By;
import org.openqa.selenium.SearchContext;
import org.openqa.selenium.WebElement;

public class ByImageSrc extends By 
{
    private final String imageByString;
    public ByImageSrc(String imageByString)
    {
        this.imageByString = imageByString;
    }

    @Override
    public List<WebElement> findElements(SearchContext context) 
    {
         List<WebElement> mockElements = context.findElements(By.xpath("//img[@src='" + imageByString + "']"));
         return mockElements;
    }
}

用法 :

WebElement element = driver.findElement(new ByImageSrc("/path/to/image"));
于 2014-08-08T00:46:18.977 回答
1

您需要对类进行子By类化并提供方法findElementfindElements方法的实现,因为这是实际元素查找的“内容”发生的地方。

然后,您应该可以正常使用它driver.FindElement

于 2013-01-11T10:06:29.170 回答
0

我知道这并不能真正回答您的问题,但为什么不直接使用 Xpath 呢?构建一个新的定位器而不是仅仅爬取 DOM 似乎需要做很多额外的工作。

例如:driver.findElement(By.Xpath("//div[@username='YourUsername']")

我可以举一个更好的例子,其中包含有关您正在使用的属性和页面的更多详细信息。

于 2013-01-10T18:39:14.037 回答
0

就像 Michiel 回答的那样,我觉得你可以用 Selenium 已经提供的东西来实现你想要的。如果这是由于开发人员更改 id 和元素名称而导致的维护开销,您可以创建一个单独的文件来跟踪您需要定位的元素。

//EG. (not Java I know :))
string usernameXPath = "//div[@username='YourUsername']";

然后,如果有变化,你可以保持这个。您甚至可以更进一步,为每个“其他类型”的元素实现一个类,然后在构造函数中围绕它放置一个 XPath。XPath 非常灵活,因为它提供了诸如 ' contains ' 和 ' parent::div' 之类的功能。也许查看W3schools 页面以获得更多 XPath 阅读。

编辑:另外值得注意的是,最新版本的 C# 绑定说明如下:

.Net:将更新 CustomFinderType 属性引入 .NET FindsByAttribute。这允许在 PageFactory 中使用自定义 By 子类。自定义查找器必须是 By 的子类,并且它必须公开一个接受字符串参数的公共构造函数。

希望这也将出现在您的下一个 Java 版本中 :)

于 2013-01-11T03:09:58.007 回答
0

你可以这样做:

private final String myLocator = "//*[contains(@id,'username') and contains (@type,'text') and contains (text(),'exactly what I want')]";

因此,您可以根据您所映射的属性编写定位器,但无需单击或选择 5 行。

此外,您可以在该定位器中使用通配符,只需将您想要用作参数的任何内容替换为“%s”,如下所示:

private final String myLocator = "//*[contains(@id,'%s') and contains (@type,'text') and contains (text(),'exactly what I want')]";

然后创建一个动态元素,例如:

private WebElement usernameSelectElement(String text) {
    return driver.findElement(By.xpath(String.format(myLocator, text)));
}

用法如下:

public void clickMyElement(text){
usernameSelectElement(text).click();
}

对于您的示例,在我看来它过于复杂。

于 2013-08-13T14:56:53.367 回答