如何通过使用 Selenium Grid 将文件从本地计算机传输到远程 Web 服务器来上传文件

Posted

技术标签:

【中文标题】如何通过使用 Selenium Grid 将文件从本地计算机传输到远程 Web 服务器来上传文件【英文标题】:How to upload a file by transfering the file from the local machine to the remote web server using Selenium Grid 【发布时间】:2020-10-17 02:20:49 【问题描述】:

使用 Selenium 网格上传文件:

代码

import java.net.MalformedURLException;
import java.net.URL;
import java.util.concurrent.TimeUnit;
import org.openqa.selenium.By;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.remote.DesiredCapabilities;
import org.openqa.selenium.remote.LocalFileDetector;
import org.openqa.selenium.remote.RemoteWebDriver;

public class Main 

    
    public static void main(String[] args) throws MalformedURLException
    
          DesiredCapabilities capabilities = DesiredCapabilities.internetExplorer();
          capabilities.setBrowserName("internet explorer");
    
          RemoteWebDriver driver = new RemoteWebDriver(new URL("http://URL:4444/wd/hub"), capabilities);
          driver.setFileDetector(new LocalFileDetector());
          driver.manage().timeouts().implicitlyWait(30, TimeUnit.SECONDS);
    
          driver.get("https://url.de/index.xhtml");
          driver.findElement(By.xpath("//*[@id='form:sdsupload']/span")).click();
        
          WebElement addFile = driver.findElement(By.xpath("//input[@type='file']"));
          ((RemoteWebElement) addFile ).setFileDetector(new LocalFileDetector());
          addFile.sendKeys("C:\\daten\\test\\test2.xml");
    

例外

Jun 26, 2020 3:47:43 PM org.openqa.selenium.remote.ProtocolHandshake createSession
INFORMATION: Detected dialect: W3C
Exception in thread "main" org.openqa.selenium.InvalidArgumentException: Attempting to upload file 'C:\daten\test\test2.xml' which does not exist.
Build info: version: '3.141.59', revision: 'e82be7d358', time: '2018-11-14T08:17:03'
System info: host: 'xxx', ip: 'xxx', os.name: 'Windows 10', os.arch: 'amd64', os.version: '10.0', java.version: '1.8.0_171'
Driver info: org.openqa.selenium.remote.RemoteWebDriver
Capabilities acceptInsecureCerts: false, browserName: internet explorer, browserVersion: 11, javascriptEnabled: true, pageLoadStrategy: normal, platform: WINDOWS, platformName: WINDOWS, proxy: Proxy(), se:ieOptions: browserAttachTimeout: 0, elementScrollBehavior: 0, enablePersistentHover: true, ie.browserCommandLineSwitches: , ie.ensureCleanSession: false, ie.fileUploadDialogTimeout: 3000, ie.forceCreateProcessApi: false, ignoreProtectedModeSettings: false, ignoreZoomSetting: false, initialBrowserUrl: http://localhost:5494/, nativeEvents: true, requireWindowFocus: false, setWindowRect: true, timeouts: implicit: 0, pageLoad: 300000, script: 30000, webdriver.remote.sessionid: ae053a22-c088-402e-8de1-f25...
Session ID: ae053a22-c088-402e-8de1-f25c4398ccbf
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
    at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
    at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
    at java.lang.reflect.Constructor.newInstance(Constructor.java:423)
    at org.openqa.selenium.remote.http.W3CHttpResponseCodec.createException(W3CHttpResponseCodec.java:187)
    at org.openqa.selenium.remote.http.W3CHttpResponseCodec.decode(W3CHttpResponseCodec.java:122)
    at org.openqa.selenium.remote.http.W3CHttpResponseCodec.decode(W3CHttpResponseCodec.java:49)
    at org.openqa.selenium.remote.HttpCommandExecutor.execute(HttpCommandExecutor.java:158)
    at org.openqa.selenium.remote.RemoteWebDriver.execute(RemoteWebDriver.java:552)
    at org.openqa.selenium.remote.RemoteWebElement.execute(RemoteWebElement.java:285)
    at org.openqa.selenium.remote.RemoteWebElement.sendKeys(RemoteWebElement.java:106)
    at de.xxx.xxx.keywords.Main.main(Main.java:41)

该文件存在于本地节点上,但不存在于远程节点上。如果该文件位于远程节点上,则效果很好。该文件存在于本地节点,但不存在于远程节点:https://i.stack.imgur.com/f31Wb.png

我读到这个:

https://www.selenium.dev/documentation/en/remote_webdriver/remote_webdriver_client/ https://www.lambdatest.com/blog/how-to-download-upload-files-using-selenium-with-java/

如何将文件传递到远程节点?

编辑

Firefox、IE 和 Edge Chromium 出现同样的错误

火狐:

Exception in thread "main" org.openqa.selenium.InvalidArgumentException: File not found: C:\daten\test\test3.xml
Build info: version: '3.141.59', revision: 'e82be7d358', time: '2018-11-14T08:17:03'
System info: host: 'xxx', ip: 'xxx', os.name: 'Windows 10', os.arch: 'amd64', os.version: '10.0', java.version: '1.8.0_171'
Driver info: org.openqa.selenium.remote.RemoteWebDriver
Capabilities acceptInsecureCerts: true, browserName: firefox, browserVersion: 60.5.0, javascriptEnabled: true, moz:accessibilityChecks: false, moz:geckodriverVersion: 0.25.0, moz:headless: false, moz:processID: 624, moz:profile: C:\Users\username\Ap..., moz:useNonSpecCompliantPointerOrigin: false, moz:webdriverClick: true, pageLoadStrategy: normal, platform: XP, platformName: XP, platformVersion: 10.0, rotatable: false, timeouts: implicit: 0, pageLoad: 300000, script: 30000, webdriver.remote.sessionid: 8801c61e-6d61-488b-8f86-c0a...
Session ID: 8801c61e-6d61-488b-8f86-c0a1fb2f2df8
    at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
    at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
    at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
    at java.lang.reflect.Constructor.newInstance(Constructor.java:423)
    at org.openqa.selenium.remote.http.W3CHttpResponseCodec.createException(W3CHttpResponseCodec.java:187)
    at org.openqa.selenium.remote.http.W3CHttpResponseCodec.decode(W3CHttpResponseCodec.java:122)
    at org.openqa.selenium.remote.http.W3CHttpResponseCodec.decode(W3CHttpResponseCodec.java:49)
    at org.openqa.selenium.remote.HttpCommandExecutor.execute(HttpCommandExecutor.java:158)
    at org.openqa.selenium.remote.RemoteWebDriver.execute(RemoteWebDriver.java:552)
    at org.openqa.selenium.remote.RemoteWebElement.execute(RemoteWebElement.java:285)
    at org.openqa.selenium.remote.RemoteWebElement.sendKeys(RemoteWebElement.java:106)
    at de.xxx.xxx.keywords.Main.main(Main.java:52)

当我将文件复制到远程客户端时,它再次运行良好:(

调试: Debug with Firefox

【问题讨论】:

【参考方案1】:

此错误消息...

Exception in thread "main" org.openqa.selenium.InvalidArgumentException: Attempting to upload file 'C:\daten\test2.xml' which does not exist.

...表示客户端计算机上不存在所需的文件。


本地文件检测器

Local File Detector 允许将文件从客户端计算机传输到远程服务器。如果测试需要将文件上传到 Web 应用程序,远程WebDriver 可以在运行时自动将文件从本地机器传输到远程 Web 服务器。这允许从运行测试的远程机器上载文件。默认不开启,可以如下开启:

Java

driver.setFileDetector(new LocalFileDetector());

Python

from selenium.webdriver.remote.file_detector import LocalFileDetector

driver.file_detector = LocalFileDetector()

C#

var allowsDetection = this.driver as IAllowsFileDetection;
if (allowsDetection != null)

   allowsDetection.FileDetector = new LocalFileDetector();

红宝石

@driver.file_detector = lambda do |args|
  # args => ["/path/to/file"]
  str = args.first.to_s
  str if File.exist?(str)
end

JavaScript

var remote = require('selenium-webdriver/remote');
driver.setFileDetector(new remote.FileDetector); 

科特林

driver.fileDetector = LocalFileDetector()

这个用例

如果您在Selenium Grid 上运行测试,那么您需要让远程驱动程序知道需要上传的文件位于本地计算机上而不是远程计算机上。在这些情况下,要将文件从客户端机器上传到远程服务器,WebDriver 可以在运行时自动将文件从本地机器传输到远程 Web 服务器,您可以使用以下代码块:

WebElement addFile = driver.findElement(By.xpath("//input[@type='file']"));
((RemoteWebElement)addFile).setFileDetector(new LocalFileDetector());
addFile.sendKeys("C:\\daten\\test2.xml");

结尾

Selecting and uploading files while running your tests on Selenium Grid

【讨论】:

我发布了带有相同错误消息和文件存在的屏幕截图的新代码 @Andreas 你能用 ChromeFirefox 试一次吗。 IE 似乎存在一些问题。 它工作:) 谢谢!我不知道是什么问题。它不适用于 Firefox、Edge Chromium 和 IE。当我重写 sendKeys 命令时,它起作用了。我不知道为什么。 非常感谢您!我认为问题是一个损坏的 xml 文件。 虽然设置了 localFileDetector,但我会间歇性地失败。 ***.com/questions/68007769/…【参考方案2】:

感谢 @DebanjanB 帮助我找到解决方案 - 我已赞成您的回复,这是另一个说明它确实有效的答案。

我的问题:

在本地,我正在对本地运行的 Selenium 服务器(运行 selenium-server-4.0.0-beta-4.jar 文件)运行 Selenium 测试,并且我也在使用 chromedriver.exe 文件。

我上传文件的测试(用 TypeScript 编写)使用:

await (
  await driver.findElement(By.xpath("//form//input[@id='upload-input']"))
).sendKeys(join(__dirname, "testfile.txt"));

在本地运行没有问题。但是在我们的 DevOps 管道中,使用 selenium/standalone-chrome 镜像运行 Docker,就像驱动程序找不到文件一样:

InvalidArgumentError: invalid argument: File not found: /home/vsts/work/1/s/selenium/tests/flows/testfile.txt

即使我们已经通过运行确认文件确实在正确的文件夹中找到:

> pwd
/home/vsts/work/1/s
> find . -name testfile.txt
./selenium/tests/flows/testfile.txt

意味着文件确实位于/home/vsts/work/1/s/selenium/tests/flows/testfile.txt

我和我的团队在 Google 上搜索并搜索了为什么会这样,并找到了 @DebanjanB 的答案。

我们没有意识到selenium/standalone-chrome Docker 映像正在运行 Selenium Grid 服务器,它是“远程”而不是“本地”的。因此驱动程序在运行“远程”时找不到文件。

解决方案

我们添加了

driver.setFileDetector(new FileDetector());

之前

await (
  await driver.findElement(By.xpath("//form//input[@id='upload-input']"))
).sendKeys(join(__dirname, "testfile.txt"));

现在,在我们的管道中针对 docker 容器运行时,我们的测试也通过了!

来自 Selenium 的文档:

本地文件检测器允许将文件从客户端计算机传输到远程服务器。例如,如果测试需要将文件上传到 Web 应用程序,远程 WebDriver 可以在运行时自动将文件从本地机器传输到远程 Web 服务器。这允许从运行测试的远程机器上传文件。

来源:https://www.selenium.dev/documentation/webdriver/remote_webdriver/#local-file-detector

我希望这会帮助那些遇到同样问题的人:-)

【讨论】:

以上是关于如何通过使用 Selenium Grid 将文件从本地计算机传输到远程 Web 服务器来上传文件的主要内容,如果未能解决你的问题,请参考以下文章

在节点机器上执行批处理文件 - Selenium Grid

如何使用Selenium-Grid

如何使用Selenium-Grid

Selenium-Grid:如何使用`user-extensions.js`

如何通过命令行查看selenium log

selenium Grid使用