获取已找到的WebElement

时间:2015-07-28 12:55:19

标签: java selenium selenium-webdriver pageobjects

是否有一种优雅的方式来获取Selenium WebElement的By定位器,我已经找到/识别出来了?

要明确这个问题:我想要用“定位器”来查找元素。我在这种情况下对特定属性或css-locator等特定定位器感兴趣。

我知道我可以解析WebElement的toString()方法的结果:

WebElement element = driver.findElement(By.id("myPreciousElement"));
System.out.println(element.toString());

输出将是例如:

  

[[FirefoxDriver:WINDOWS(....)上的firefox] - > id:myPreciousElement]

如果你通过xpath找到你的元素:

WebElement element = driver.findElement(By.xpath("//div[@someId = 'someValue']"));
System.out.println(element.toString());

然后你的输出将是:

  

[[FirefoxDriver:WINDOWS(....)上的firefox] - > xpath:// div [@someId ='someValue']]

所以我目前编写了自己的方法来解析这个输出并给我“重新创建”的By locator。


但是是否有更优雅的方式在Selenium中实现以获取用于查找元素的By定位器?

到目前为止我找不到一个。 p>

如果您确定没有开箱即用,您能否想到API创建者可能无法提供此功能的任何原因?



*尽管这与这个问题无关,如果有人想知道为什么你需要这个功能,只需要两个例子:

  • 如果您使用PageFactory,您很可能不会将定位器作为Page类中的成员变量,但在使用页面元素时可能会在以后需要它们。
  • 你正在使用那些只使用没有PageFactory的页面对象模式的人的API,因此希望你交出定位器而不是元素本身。*

7 个答案:

答案 0 :(得分:5)

答案是。默认情况下,您无法从以前找到的WebElement中提取By by = By.id("someId"); WebElement e = driver.findElement(by);

话虽如此 - 可以实现自定义解决方案,但Selenium并不提供这种开箱即用的解决方案。

考虑以下内容,关于“为什么”..

By

您已拥有e.getBy()个对象,因此您无需拨打{{1}}

之类的内容

我将来可能会实现这样的事情,但没有承诺。再次 - 它只是糖。

答案 1 :(得分:5)

不,没有。我已经实现了一个可能的解决方案作为代理:

public class RefreshableWebElement implements WebElement {

    public RefreshableWebElement(Driver driver, By by) {
        this.driver = driver;
        this.by = by;
    }

    // ...

    public WebElement getElement() {
        return driver.findElement(by);
    }

    public void click() {
        getElement().click();
    }

    // other methods here
}

答案 2 :(得分:1)

对我来说,我使用commons-lang3

<dependency>
    <groupId>org.apache.commons</groupId>
    <artifactId>commons-lang3</artifactId>
    <version>3.7</version>
</dependency>

对于远程Web元素,请使用以下方法:

protected String getLocator(WebElement element) {
        try {
            Object proxyOrigin = FieldUtils.readField(element, "h", true);
            Object locator = FieldUtils.readField(proxyOrigin, "locator", true);
            Object findBy = FieldUtils.readField(locator, "by", true);
            if (findBy != null) {
                return findBy.toString();
            }
        } catch (IllegalAccessException ignored) {
        }
        return "[unknown]";
    }

答案 3 :(得分:0)

我已经编写了此实用程序函数,该函数返回定位器策略+定位器值的字符串组合。

private String getLocatorFromWebElement(WebElement element) {

    return element.toString().split("->")[1].replaceFirst("(?s)(.*)\\]", "$1" + "");
}

答案 4 :(得分:0)

Selenium没有提供任何优雅的方法。这太可怕了

1)PageObjectPageFactory表示我们在WebElements类中有Page,但是没有这些元素的定位符。

2)如果使用webElement.findElement(By)找到元素作为当前元素的后代,那么即使我将父级的定位符存储在变量中,我也没有该后代的定位符。

3)如果我使用返回元素的findElements的{​​{1}}函数,那么我没有每个特定元素的定位符。

4)为元素设置定位符很有用,至少因为以定位符为参数的List的实现要比以ExpectedConditions为参数的ExpectedConditions更好。

对我来说Selenium是一个构思不佳且实施不佳的库

答案 5 :(得分:0)

从硒的角度来看,目前还没有特定的方法。您可以做的是编写您的自定义方法。只需打印您拥有的webElement,即可了解使用哪种选择器类型和路径的线索。

看起来像这样

  

[[ChromeDriver:XP上的Chrome(d85e7e220b2ec51b7faf42210816285e)]-> xpath:// input [@ title ='Search']]

现在,您需要做的是提取定位器及其值。您可以尝试这样的事情

`private通过getByFromElement(WebElement元素){

    By by = null;
    //[[ChromeDriver: chrome on XP (d85e7e220b2ec51b7faf42210816285e)] -> xpath: //input[@title='Search']]
    String[] pathVariables = (element.toString().split("->")[1].replaceFirst("(?s)(.*)\\]", "$1" + "")).split(":");

    String selector = pathVariables[0].trim();
    String value = pathVariables[1].trim();

    switch (selector) {
        case "id":
            by = By.id(value);
            break;
        case "className":
            by = By.className(value);
            break;
        case "tagName":
            by = By.tagName(value);
            break;
        case "xpath":
            by = By.xpath(value);
            break;
        case "cssSelector":
            by = By.cssSelector(value);
            break;
        case "linkText":
            by = By.linkText(value);
            break;
        case "name":
            by = By.name(value);
            break;
        case "partialLinkText":
            by = By.partialLinkText(value);
            break;
        default:
            throw new IllegalStateException("locator : " + selector + " not found!!!");
    }
    return by;
}

`

答案 6 :(得分:0)

当我遇到需要 By 定位器用于 ExpectedConditions 并且我在页面对象工厂中有定位器时,我的解决方案是使用一个包含定位器的字符串,然后构建我的 By 对象和元素定位器

public class PageObject {
    private static final String XPATH_NAME = "...";

    public @iOSXCUITFindBy(xpath = XPATH_NAME)
    List<MobileElement> mobileElementName;

    public By getByXPath(){
        return new By.ByXPath(XPATH_NAME);
    }

    public PageObject() {
        PageFactory.initElements(driver, this);
    }
}