我正在使用Capybara Selenium运行无头Chrome,效果很好,除了我无法弄清楚如何使用远程调试。当我添加--remote-debugging-port=4444
或--remote-debugging-port=9222
或--remote-debugging-port=9521
时,Selenium不再连接到浏览器来运行测试。
如何让远程调试工作?这是我的参考代码:
Capybara.register_driver :selenium do |app|
# from https://github.com/SeleniumHQ/selenium/issues/3738
capabilities = Selenium::WebDriver::Remote::Capabilities.chrome(loggingPrefs: {browser: 'ALL'})
options = Selenium::WebDriver::Chrome::Options.new
options.add_argument '--disable-infobars' # hide info bar about chrome automating test
# if we don't use this flag, every selenium test will die with the error:
# "unknown error: Chrome failed to start: exited abnormally"
options.add_argument '--no-sandbox'
# BREAKS THINGS if uncommented
# options.add_argument '--remote-debugging-port=4444'
options.add_argument '--headless'
options.add_argument '--window-size=1600,2400'
options.add_preference('profile.default_content_settings.popups', 0)
options.add_preference('download.default_directory', DownloadHelpers::PATH.to_s)
Capybara::Selenium::Driver.new(
app,
clear_local_storage: true,
clear_session_storage: true,
browser: :chrome,
options: options,
desired_capabilities: capabilities,
)
end
答案 0 :(得分:4)
自chrome 67 and chromedriver 2.39起,chromedriver现在正确使用您使用--remote-debugging-port
指定的端口。这消除了相当多的复杂性from my answer above。我现在采取的步骤(适用于需要使用chrome_remote配置下载设置的用例)如下:
它使用了nodejs库crmux - 它允许多个客户端同时连接到chrome的远程调试端口。
npm install crmux -g
在之前启动chromedriver(Capybara::Selenium::Driver.new
),您需要spawn
一个单独的线程,它将启动crmux
你和chromedriver通过在Capybara(4444)指定的你的端口与chrome本身进行通信:
crmux --port=4444 --listen=4444
您可能希望在主脚本/线程中的sleep 3
命令之后添加spawn
,以便在继续测试启动之前为crmux提供时间。
然后,您可以使用chrome_remote(例如)使用端口 4444 访问chrome,而capybara正在执行此操作。
答案 1 :(得分:0)
更新:如果使用Chrome 67 / chromedriver 2.39之后的版本,my alternative answer above provides a simpler solution
此处的核心问题是Chromedriver还使用远程调试端口连接与Chrome进行通信。这使用websocket协议,它只支持一次连接的单个客户端。通常,当chromedriver启动chromedriver进程时,它将选择一个随机的免费TCP端口号并使用它来访问远程调试端口。但是,如果您指定--remote-debuggging-port=9222
,则会使用您请求的调试端口打开Chrome,但是chromedriver会默默地继续尝试使用此随机端口号打开连接。
我最终得到的解决方案受comment 20 in this chromedriver issue的启发。它需要相当多的代码才能使它工作,但是能够稳定地运行。它使用了nodejs库crmux - 它允许多个客户端同时连接到chrome的远程调试端口。
npm install crmux -g
Capybara::Selenium::Driver.new
),你需要spawn
一个单独的线程,它会做一些事情:寻找chromedriver尝试的远程调试端口用于连接到chrome,然后使用它来启动crmux
。一旦发生这种情况,Capybara等将正常工作。这个代码是:
$chrdrv_wait_timeout = 60
$chrdrv_exe = "chromedriver.exe"
def get_netstat_output
stdout = `netstat -a -b -n`
stat_lines = stdout.split("\n")
stat_lines
end
def try_get_requested_port
socket_state = "SYN_SENT" # i.e. sent with no reply
statout = get_netstat_output
n = statout.length
i = 0
loop do
i += 1
# find lines relating to chromedriver
exe_match = /^ +\[#{$chrdrv_exe}\]$/.match statout[i]
if exe_match != nil
# check preceeding lines which should contain port info
port_match = /TCP.*:([0-9]+)\W+#{socket_state}/.match statout[i-1]
if port_match != nil
return port_match[1].to_i
end
end
break unless i < n
end
return nil
end
def get_tcp_port_requested_by_chromedriver
i = 1
loop do
puts "Waiting for #{$chrdrv_exe}: #{i}"
port = try_get_requested_port
if port != nil
return port
end
break unless i < $chrdrv_wait_timeout
sleep 1
i += 1
end
raise Exception, "Failed to get TCP port requested by #{$chrdrv_exe} (gave up after #{$chrdrv_wait_timeout} seconds)"
end
(我在Windows中工作:对于Mac / Linux,netstat语法/输出可能不同,因此代码需要调整;关键是你需要它来输出可执行文件所有者每个连接条目的> - 并解析与chromedriver相关的位以获得有问题的端口。
一旦找到随机端口(我将 12225 作为示例),后台ruby脚本就可以执行crmux进程,该进程将使用chrome重新组合chromedriver本身通过Capybara(4444)中指定的端口你:
crmux --port=4444 --listen=12225
最后,这个单独的脚本将发现的侦听端口保存到文本文件中。这允许运行capybara的主脚本/线程通过从该文件读入端口来知道它可以用来访问chrome(通过crmux的多路复用连接)的端口号。因此,您可以使用chrome_remote来使用端口 12225 来访问chrome,例如,虽然Capybara正在做其事情。
答案 2 :(得分:0)
更新我的ChromeDriver为我修复了它。我没有做任何其他事情。在尝试开始测试之前它会挂起。
具体来说,我使用ChromeDriver 2.36并升级到ChromeDriver 2.40。我不认为Chrome版本是个问题,因为我之前和之后都在Chrome 67上。
以下是我注册驱动程序的方法:
Capybara.register_driver :headless_chrome do |app|
capabilities = Selenium::WebDriver::Remote::Capabilities.chrome(
chromeOptions: { args: %w[headless window-size=1280,960 remote-debugging-port=9222] }
)
Capybara::Selenium::Driver.new(app, browser: :chrome, desired_capabilities: capabilities)
end
之后我运行了我的测试,调试器(binding.pry
)放置在我想要检查的位置。然后当我点击调试器时,我在Chrome的正常实例中导航到http://localhost:9222/,并且能够按照链接查看无头Chrome实例中发生的情况,包括我需要的浏览器控制台输出。