简体   繁体   English

selenium chrome 驱动程序的 getText() 方法有时会返回一个空字符串

[英]getText() method of selenium chrome driver sometimes returns an empty string

I have a curious case where the selenium chrome driver getText() method (java) returns an empty string for some elements, even though it returns a non-empty string for other elements with the same xpath .我有一个奇怪的情况,即 selenium chrome 驱动程序getText()方法(java)为某些元素返回一个空字符串,即使它为具有相同xpath其他元素返回一个非空字符串。 Here is a bit of the page.这是页面的一部分。

<div __gwt_cell="cell-gwt-uid-223" style="outline-style:none;">
<div>Text_1</div>
<div>Text_2</div>
<div>Text_3</div>
<div>Text_4</div>
<div>Text_5</div>
<div>Text_6</div>
</div>

for each of the inner tags, I can get valid return values for getTagName() , getLocation() , isEnabled() , and isDisplayed() .对于每个内部标签,我可以获得getTagName()getLocation()isEnabled()isDisplayed()有效返回值。 However, getText() returns an empty string for some of the divs.但是,getText() 会为某些 div 返回一个空字符串。

Further, I notice that if I use the mac chrome driver, it is consistently the 'Text_5' for which getText() returns an empty string.此外,我注意到如果我使用 mac chrome 驱动程序,它始终是getText()返回空字符串的“Text_5”。 If I use the windows chrome driver, it is , it is consistently the 'Text_2' for which getText() returns an empty string.如果我使用 windows chrome 驱动程序,它始终是getText()返回空字符串的“Text_2”。 If I use the firefox driver, getText() returns the expected text from all the divs.如果我使用 firefox 驱动程序, getText()会从所有 div 返回预期的文本。

Has anyone else had this difficulty?有没有其他人遇到过这种困难?

In my code, I use something like this…在我的代码中,我使用了这样的东西......

ArrayList<WebElement> list = (ArrayList<WebElement>) driver.findElements(By.xpath(“my xPath here”));
for (WebElement e: list) System.out.println(e.getText());

As suggested below, here is the actual xPath I am using.如下所示,这是我正在使用的实际xPath The page snippet above deals with the last two divs.上面的页面片段处理最后两个 div。

//*[@class='gwt-DialogBox']//tr[contains(@class,'data-grid-table-row')]//td[contains(@class,'lms-assignment-selection-wizard-cell')]/div/div

Update: The textContent attribute is a better option and supported across the majority of browsers.更新: textContent属性是一个更好的选择,大多数浏览器都支持。 The differences are explained in detail at this blog post:innerText vs. textContent这篇博文详细解释了这些差异:innerText vs. textContent

As an alternative, the innerText attribute will return the text content of an element which exists in the DOM.作为替代方案, innerText属性将返回存在于 DOM 中的元素的文本内容。

element.getAttribute("innerText")

The isDisplayed() method can sometimes trip over when the element is not really hidden but outside the viewport;当元素不是真正隐藏而是在视口之外时, isDisplayed()方法有时会被绊倒; getText() returns an empty string for such an element. getText()为这样的元素返回一个空字符串。

You can also bring the element into the viewport by scrolling to it using javascript, as follows:您还可以通过使用 javascript 滚动到该元素将元素带入视口,如下所示:

((JavaScriptExecutor)driver).executeScript("arguments[0].scrollIntoView(true);", element);

and then getText() should return the correct value.然后getText()应该返回正确的值。

Details on the isDisplayed() method can be found in this SO question:可以在这个 SO 问题中找到有关isDisplayed()方法的详细信息:

How does Selenium WebDriver's isDisplayed() method work Selenium WebDriver 的 isDisplayed() 方法是如何工作的

WebElement.getAttribute("value") 应该可以帮助你!!

This is not a solution, so I don't know if it belongs in an answer, but it's too long for a comment and includes links, so I'm putting it an answer.这不是解决方案,所以我不知道它是否属于答案,但是评论太长并且包含链接,所以我将其作为答案。

I have had this issue as well.我也有这个问题。 After doing some digging, it seems that the problem arises when trying to get the text of an element that is not visible on the screen.(As @Faiz comments above.)This can happen if the element is not scrolled to, or if you scroll down and the element is near the top of the document and no longer visible after the scroll.在做了一些挖掘之后,似乎在尝试获取屏幕上不可见的元素的文本时出现了问题。(正如上面@Faiz 评论的那样。)如果元素没有滚动到,或者如果你向下滚动,元素靠近文档顶部,滚动后不再可见。 I see you have a FindElements() call that gets a list of elements.我看到您有一个 FindElements() 调用来获取元素列表。 At least some are probably not visible;至少有些可能是不可见的; you can check this by trying boolean b = webElement.isDisplayed();您可以通过尝试boolean b = webElement.isDisplayed();来检查这一点boolean b = webElement.isDisplayed(); on each element in the list and checking the result.在列表中的每个元素上并检查结果。 (See here for a very long discussion of this issue that's a year old and still no resolution.) (请参阅 此处对这个问题进行了很长时间的讨论,该问题已有一年之久,仍然没有解决方案。)

Apparently, this is a deliberate design decision (see here );显然,这是一个深思熟虑的设计决定(请参阅此处); gettext on invisible elements is supposed to return empty.不可见元素上的 gettext 应该返回空。 Why they are so firm about this, I don't know.为什么他们如此坚定,我不知道。 Various workarounds have been suggested, including clicking on the element before getting its text or scrolling to it.已经提出了各种解决方法,包括在获取其文本或滚动到该元素之前单击该元素。 (See above link for example code for the latter.) I can't vouch for these because I haven't tried them, but they're just trying to bring the element into visiblity so the text will be available. (有关后者的示例代码,请参见上面的链接。)我无法保证这些,因为我还没有尝试过,但他们只是试图使元素可见,以便文本可用。 Not sure how practical that is for your application;不确定这对您的应用程序有多实用; it wasn't for mine.这不是给我的。 For some reason, FirefoxDriver does not have this issue, so that's what I use.出于某种原因,FirefoxDriver 没有这个问题,所以这就是我使用的。

I'm sorry I can't give you a better answer - perhaps if you submit a bug report on the issues page they'll see that many people find it to be a bug rather than a feature and they'll change the functionality.很抱歉,我不能给你一个更好的答案——也许如果你在问题页面上提交错误报告,他们会看到很多人发现它是一个错误而不是一个功能,他们会改变功能。

Good luck!祝你好运! bsg bsg

EDIT编辑

See this question for a possible workaround.有关可能的解决方法,请参阅 此问题 You won't be able to use it exactly as given if isDisplayed returns true, but if you know which element is causing the issue, or if the text is not normally blank and you can set an 'if string is empty' condition to catch it when it happens, you can still try it.如果 isDisplayed 返回 true,您将无法完全按照给定的方式使用它,但是如果您知道哪个元素导致了问题,或者文本通常不是空白并且您可以设置“如果字符串为空”条件来捕获当它发生时,你仍然可以尝试它。 It doesn't work for everyone, unfortunately.不幸的是,它并不适用于所有人。

NEW UPDATE I just tried the answer given below and it worked for me.新更新我刚刚尝试了下面给出的答案,它对我有用。 So thanks, Faiz!所以谢谢你,法兹!

for (int count=0;count<=sizeofdd;count++)
{       
   String GetInnerHTML=getddvalue.get(count).getAttribute("innerHTML");
}

where, 1. getddvalue is the WebElement 2. sizeofdd is the size of getddvalue其中, 1. getddvalue 是 WebElement 2. sizeofdd 是 getddvalue 的大小

element.getAttribute("innerText")为我工作,当getText()返回空时。

I encountered a similar issue recently.我最近遇到了类似的问题。

I had to check that the menu tab "LIFE EVENTS" was present in the scroll box.我必须检查滚动框中是否存在菜单选项卡“LIFE EVENTS”。 The problem is that there are many menu tabs and you are required to scroll down to see the rest of the menu tabs.问题是有很多菜单选项卡,您需要向下滚动才能看到其余的菜单选项卡。 So my initial solution worked fine with the visible menu tabs but not the ones that were out of sight.所以我最初的解决方案适用于可见的菜单选项卡,但不适用于那些看不见的选项卡。

I used the xpath below to point selenium to the parent element of the entire scroll box.我使用下面的 xpath 将 selenium 指向整个滚动框的父元素。

@FindBy(xpath = "//div[contains(@class, 'menu-tree')]")
protected WebElement menuTree;

I then created a list of WebElements that I could increment through.然后我创建了一个我可以递增的 WebElements 列表。 The solution worked if the menu tab was visible, and returned a true.如果菜单选项卡可见,该解决方案有效,并返回 true。 But if the menu tab was out of sight, it returned false但是如果菜单选项卡不在视线范围内,则返回 false

public boolean menuTabPresent(String theMenuTab) {
    List<WebElement> menuTabs = new ArrayList<WebElement>();
    menuTabs = menuTree.findElements(By.xpath("//i/following-sibling::span"));

    for(WebElement e: menuTabs) {
        System.out.println(e.getText());
        if(e.getText().contains(theMenuTab)) {
            return true;
        }
    }
    return false;
}

I found 2 solutions to the problem which both work equally well.我找到了解决这个问题的2 个解决方案,它们都同样有效。

    for(WebElement e: menuTabs) {
        scrollElementIntoView(e); //Solution 1
        System.out.println(e.getAttribute("textContent")); //Solution 2
        if(e.getAttribute("textContent").contains(theMenuTab)) {
            return true;
        }
    }
    return false;

Solution 1 calls the method below.解决方案 1 调用下面的方法。 It results in the scroll box to physically move down while selenium is running.这会导致在 selenium 运行时滚动框物理向下移动。

protected void scrollElementIntoView(WebElement element) {
    ((JavascriptExecutor) driver).executeScript("arguments[0].scrollIntoView(true)", element);
}

Solution 2 gets the text content (even for the menu tabs not currently visible) of the attribute that you are pointing to.解决方案 2 获取您指向的属性的文本内容(即使对于当前不可见的菜单选项卡)。 Thus doing the job properly that .getText() was not able to do in this situation.因此正确地完成了 .getText() 在这种情况下无法完成的工作。

if you don't care about isDisplayed or scrolling position, you can also write如果你不关心 isDisplayed 或滚动位置,你也可以写

String text = ((JavaScriptExecutor)driver).executeScript("return $(arguments[0]).text();", element);

or without jquery或者没有 jquery

String text = ((JavaScriptExecutor)driver).executeScript("return arguments[0].innerText;", element);

Related to getText() I have also an issue and I resolved so:getText()我也有一个问题,我解决了这个问题:

WebElement errMsg;
errMsg = driver.findElement(By.xpath("//div[@id='mbr-login-error']"));
WebElement parent = driver.findElement(By.xpath("//form[@id='mbr-login-form']"));
List<WebElement> children = parent.findElements(By.tagName("div")); 
System.out.println("Size is: "+children.size());
//((JavascriptExecutor)driver).executeScript("arguments[0].scrollIntoView(true);", children);
for(int i = 0;i<children.size();i++)
{
    System.out.println(i + " " + children.get(i).getText());
}
int indexErr = children.indexOf(errMsg);
System.out.println("index " + indexErr);
Assert.assertEquals(expected, children.get(indexErr).getText());

None of the above solutions worked for me.以上解决方案都不适合我。

Worked for me:为我工作:

add as a predicate of xpath the length of string greater than 0:添加大于 0 的字符串长度作为 xpath 的谓词:

String text = wait.until(ExpectedConditions.presenceOfElementLocated(By.xpath("//span[string-length(text()) > 0]"))).getText();

Mine is python , but the core logic is similar:我的是python ,但核心逻辑是相似的:

  • webElement.text
  • webElement.get_attribute("innerText")
  • webElement.get_attribute("textContent")

Full code:完整代码:

def getText(curElement):
    """
    Get Selenium element text

    Args:
        curElement (WebElement): selenium web element
    Returns:
        str
    Raises:
    """
    # # for debug
    # elementHtml = curElement.get_attribute("innerHTML")
    # print("elementHtml=%s" % elementHtml)

    elementText = curElement.text # sometime NOT work

    if not elementText:
        elementText = curElement.get_attribute("innerText")

    if not elementText:
        elementText = curElement.get_attribute("textContent")

    # print("elementText=%s" % elementText)
    return elementText

Calll it:调用它:

curTitle = getText(h2AElement)

hope is useful for you.希望对你有用。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM