如何在java中为Selenium webdriver编写自己的自定义定位器?

时间:2013-01-10 17:15:23

标签: java selenium webdriver selenium-webdriver browser-automation

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

实施例: 选择您的用户名:

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

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

如果有人能给我们一些好主意,我怎么能重写BY类来添加我自己的定位器,这将是非常有用的。

提前感谢您的帮助。

5 个答案:

答案 0 :(得分:4)

使用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"));

答案 1 :(得分:1)

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

然后,您应该能够使用普通的driver.FindElement

答案 2 :(得分:0)

我知道这并没有真正回答你的问题,但为什么不只是使用Xpath? 看起来构建新的定位器而不是仅仅抓取DOM会有很多额外的工作。

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

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

答案 3 :(得分:0)

很像Michiel的回答,我觉得你可以用Selenium提供的东西达到你想要的效果。如果由于开发人员更改id和元素名称而需要避免维护开销,则可以创建一个单独的文件来跟踪需要定位的元素。

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

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

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

.Net:介绍将CustomFinderType属性更新到     .NET FindsByAttribute。这允许使用自定义By子类     PageFactory。自定义查找器必须是By和的子类     它必须公开一个带有字符串参数的公共构造函数。

Hopefull这也适用于你的下一个Java版本:)

答案 4 :(得分: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();
}

对于你所拥有的例子,我认为它过于复杂了。