如何在Selenium WebDriver中逐个输入字符到文本字段中?

6
如何在Selenium WebDriver中逐个输入字符到文本字段?我已经使用了以下代码,但它不起作用。
getDriver().findElement(By.id("PhoneNumber")).sendKeys(Keys.chord("9876544322"));

有人能提供解决这个问题的建议吗?


2
为什么不直接将字符串传递给 sendKeys()getDriver().findElement(By.id("PhoneNumber")).sendKeys("9876544322"); - alecxe
1
由于某些输入字段会在用户输入时做出反应,例如在输入3个字符后开始搜索,在按下另一个字符后取消搜索并开始搜索4个字符的字符串等,因此逻辑可能相当复杂。 - Andrei Volgin
7个回答

12

以下是我使用Selenium Webdriver(Java语言)逐个字符发送文本的方法。这种方法可以在后端验证每次按下的字符是否存在于输入框中。普通的element.sendKeys()对我来说有2次在5次中无法正常工作 - 最后一个字符会丢失,我猜测这可能是Selenium Webdriver的某些问题导致的,具体我也不清楚。尝试以下代码,对我而言100%正常工作。

public void TypeInField(String xpath, String value){
    String val = value; 
    WebElement element = driver.findElement(By.xpath(xpath));
    element.clear();

    for (int i = 0; i < val.length(); i++){
        char c = val.charAt(i);
        String s = new StringBuilder().append(c).toString();
        element.sendKeys(s);
    }       
}

如您所见,我获取了需要输入的值,在for循环中,我将每个字符转换为字符串并将其发送到文本框。此外,我还有一个xpath搜索,您可以将其更改为id、classname或任何您想要的内容。


1
这个解决方案对我非常完美,除了我必须在每个 sendkeys 调用之后放置 100 毫秒的休眠。我们的应用程序为每个字符类型进行后端调用,并返回搜索结果。 - vikramvi
非常感谢。我在我的自动化项目中尝试了几种解决方案,包括JavaScript、Jquery等所有解决方案,但都遇到了一些问题。这个解决方案就像人类一样打字,而且非常好用。非常感谢。 - Onur Baskirt
1
@vikramvi,如果应用程序/服务器之间存在延迟,最好等待一下,否则可能会失败。Onur,很高兴我能帮到你 :) - Marțiș Paul
太棒了!帮我解决了几个小时的问题。简直让我发疯! - user3356141
我建议在字符之间设置可变延迟 - 在0毫秒延迟下有效的方法可能在100毫秒延迟或500毫秒延迟下无效。 - Andrei Volgin
1
我能省略 StringBuilder 直接写以下代码吗? for (int i = 0; i < val.length(); i++) { element.sendKeys(val.charAt(i).toString()); Thread.Sleep(100);} - Abhi3106

9
如果你想让你的sendKeys更加自然,我使用了类似下面的代码:
private static void sendHumanKeys(WebElement element, String text) {
    Random r = new Random();
    for(int i = 0; i < text.length(); i++) {
        try {
            Thread.sleep((int)(r.nextGaussian() * 15 + 100));
        } catch(InterruptedException e) {}
        String s = new StringBuilder().append(text.charAt(i)).toString();
        element.sendKeys(s);
    }
}

它会延迟100ms发送按键,但平均值只有100ms。它会创建一个正态分布,其平均值为100ms,标准差为15ms。

2
太棒了!对我来说完美无缺。我喜欢nextGaussian!真是个不错的点睛之笔。 人是随机的,而计算机则是精确的。哈哈! :-) - Tihamer

5
sendKeys()方法按顺序输入字符,但有时候运行速度非常快,会被看作是复制/粘贴操作。但实际上,它旨在通过键入来模拟用户输入文本。根据sendKeys() JavaDoc的说明:

/** 使用此方法模拟输入元素中的内容,这可能会设置其值。*/

如果您想要减慢它的速度,可以编写一个接受WebElement和String参数的方法,将String转换为charsequence[],然后使用for循环并在每个数组索引处输入.sendKeys(),然后加上Thread.sleep()。不过,这种方式效率极低,因为sendKeys()将String识别为charsequence[](在Java中,String 一个charsequence[])。添加Thread.sleep()只会使测试变得毫无意义。
老实说,sendKeys()适合您所描述的需求。它是模拟用户键盘输入的最佳方式,只是速度非常快。

1
"...它只是快速地执行" - 这正是问题所在。有些JavaScript没有时间去反应 - 或者它的反应并不像对真实用户那样。如果一个输入与个别字符相关的逻辑,则必须创建尽可能接近真实人类行为的测试 - "粘贴" / 快速输入整个字符串只是可能使用情况之一。 - Andrei Volgin
字符串是一个CharSequence,而不是CharSequence[]。 - JakeRobb
就像Andrei Volgin所说的那样,sendKeys有时对于网页来说太快了,特别是当它返回服务器搜索可能的完成时。 - Tihamer

3

我将Java Selenium代码转换为Python函数。请参考以下代码,并根据您想要使用的元素进行微调:

def TypeInField(xpath, myValue):
    val = myValue
    elem = driver.find_element_by_xpath(xpath)
    c = ""
    for i in range(0, len(val)):
      c += val[i]
      elem.send_keys(c)
      time.sleep(3)
    elem.send_keys(Keys.ENTER)

3

.chord()会同时按下所有按键。不太适合于字段输入。

.sendKeys()方法将接受一个字符串。只需将您的输入作为参数传递,然后尝试使用它。

driver.findElement(By.id("element")).sendKeys("Field Input Text");

driver.findElement(By.id("element")).sendKeys("字段输入文本");sendKeys("字段输入文本") --> 它将直接将文本放入文本字段中。我想要一个解决方案,可以像我们打字一样逐个输入字符。 - Rajendra Narayan Mahapatra
sendKeys模拟用户键盘输入,逐个字符地输入字符串。 - Jess

1

当我想逐个字母地输入字符串时,在我的测试中,我使用这个函数。

public void typeOnLetterByLetter(WebElement webElement, String value, long waitBetweenLetters, ChronoUnit unitTime) {
    clear(webElement);
    Arrays.asList(value.toCharArray()).forEach(letter -> {
        typeOn(webElement, String.valueOf(letter));
        pause(waitBetweenLetters, unitTime);
    });
}

private void pause(long time, ChronoUnit unitTime) {
    try {
        Thread.sleep(Duration.of(time, unitTime).toMillis());
    } catch (InterruptedException ignore) {
    }
}

你没有像暂停那样定义清晰或typeOn。 - Tihamer

1
这是我在C#中的实现方法。
    public void TypeInFieldCharByChar(IWebElement element,string text)
    {
        var strBuilder = new StringBuilder();

        for (int i = 0; i < text.Length; i++)
        {
            Thread.Sleep(100);
            strBuilder.Append(text[i]);
            element.SendKeys(strBuilder.ToString());
            strBuilder.Clear();
        }
    }

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接