gpt4 book ai didi

poltergeist - 使用 Poltergeist,Phantom JS 实例在每次 rspec 运行期间都不会退出

转载 作者:行者123 更新时间:2023-12-02 21:53:28 27 4
gpt4 key购买 nike

在 rspec 执行的每个 poltergeist 测试中,如果我使用以下命令创建新 session :

Capybara.session_name="some_session_name"

phantomjs 实例作为子进程启动,并且在测试结束之前永远不会退出,从而导致我的构建服务器上出现 OOM。

我认为这是由于未能调用 driver.quit,如 readme of Poltergeist 中所述。 :

If you run a few capybara sessions manually please make sure you've called session.driver.quit when you don't need session anymore. Forgetting about this causes memory leakage and your system's resources can be exhausted earlier than you may expect.

但是,我在测试的 after block 中调用 page.driver.quit

下面是我的 block 后代码。 $adhoc_sessions 是我每次设置 Capybara.session_name 时填充的全局变量,其值与 Capybara.session_name 上设置的值匹配。

config.after(:each) do
if example.metadata[:js]

$adhoc_sessions.each do |session_name|
Capybara.using_session( session_name ) do
page.driver.quit
end
end
$adhoc_sessions.clear
end

关于我可以在这里做得更好的任何建议吗?我是否未能调用某些清理命令?

最佳答案

我找到了一个有两个限制的解决方案:

  1. 我不认为你可以在 Capybara 中安全地调用 driver.quit获取私有(private)@session_pool的访问权限,因为Capybara有一旦 session 被放置,就无法让用户从池中删除 session 因此,如果您在 session 上调用 driver.quit,则无法删除该 session 从池中删除,最终 capybara 会尝试重置! session ,导致Poltergeist 抛出 IOError 因为它是内部的通过 websocket 的通信未连接。
  2. 如果你这样做每次测试运行后都会破坏整个 session 池,并退出每次测试最终,每次 session 中都会出现恶作剧驱动程序您将遇到打开文件过多错误。即:

重新创建 TOO MANY OPEN FILES 错误的方法 - 不要使用此!!

# you have to do quite a few test runs to cause the open files error
config.append_after(:each) do
session_pool = Capybara.instance_variable_get("@session_pool")
session_pool.each do | key, value |
value.driver.quit
end
session_pool.clear
end

我相信这是一个真正的吵闹鬼错误,但我不在乎......这就是为什么......在运行上面的代码时,我注意到创建一个吵闹鬼 session 是一个明显缓慢且资源密集型的操作。因此,我决定宁愿拥有一个永远不会消失的 session 池……就像 Capybara 的设计方式一样。

这种方法的唯一问题是像我一样使用 Capybara.session_name ,即在每个测试的基础上提出任意测试名称。也许在一个测试中我希望每个 session_name 与用户的数据库 ID 相同。或者我可能会想出 5 个在测试中使用的常量,并为不同的测试使用 5 个不同的常量。换句话说,我可能在我的测试套件中使用数百个 session_name,但对于任何给定的测试,我最多只有少数几个 session 。因此,一个好的解决方案重用吵闹 session ,但让我在每次测试运行时使用任意 session 名称。

这是我的解决方案

spec/utilities.rb

# holds a single test's session name's, mapped to pooled session names
$capybara_session_mapper = {}

# called after each test,
# to make sure each test run has it's own map of session names
def reset_session_mapper
$capybara_session_mapper.clear
end

# manages the mapped session name
def mapped_session_name(session_name)
return :default if session_name == :default # special treatment for the built-in session
$capybara_session_mapper[session_name] ||= $capybara_session_mapper.length
end

# in place of ever using Capybara.session_name directly,
# this utility is used to handle the mapping of session names in a way across all tests runs
def in_client(name)
Capybara.session_name = mapped_session_name(session_name)

yield
end

在 *spec_helper.rb* 中:

config.after(:each) do
Capybara.reset_sessions!
reset_session_mapper
end

直接使用 in_client 而不是 Capybara.session_name 的示例测试:

it "can't see a private thing until it is made public" do

in_client(user1.id) do
visit '/some/private/thing'
expect(page).to have_selector('#private-notice')
end

in_client(user2.id) do
visit '/expose/some/private/thing'
end

in_client(user1.id) do
visit '/some/private/thing`
expect(page).to have_selector('#private-content')
end
end

-- copied from my github answer

关于poltergeist - 使用 Poltergeist,Phantom JS 实例在每次 rspec 运行期间都不会退出,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20107326/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com