在由rspec执行的每个poltergeist测试中,如果我使用以下命令创建新会话:
Capybara.session_name="some_session_name"
一个phantomjs实例作为子进程启动,并且在测试结束之前永远不会退出,从而导致构建服务器上出现OOM.
我相信这是由于未能调用driver.quit,如自使者Poltergeist所述:
如果您手动运行几个capybara会话,请确保在不再需要会话时调用session.driver.quit.忘记这一点会导致内存泄漏,并且您的系统资源可能会比您预期的更早耗尽.
然而,我呼吁page.driver.quit在after我的测试块.
下面是我的后块代码. $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
Run Code Online (Sandbox Code Playgroud)
关于我能在这里做得更好的建议吗?我没有打电话给一些清理命令吗?
我找到了一个来自两个限制的解决方案:
重新创建 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
Run Code Online (Sandbox Code Playgroud)
我相信这是一个真正的 poltergeist bug,但我不在乎......这就是为什么......在运行上面的代码时,我注意到创建 poltergeist 会话是一个明显缓慢且资源密集型的操作。所以,我决定我宁愿有一个永远不会消失的会话池……就像 Capybara 的设计方式一样。
这种方法的唯一问题是像我一样使用 Capybara.session_name ,即在每个测试的基础上提出任意测试名称。也许在一个测试中我希望每个 session_name 与用户的数据库 ID 相同。或者我可能会想出 5 个在测试中使用的常量,并为不同的测试使用 5 个不同的常量。换句话说,我可能在我的测试套件中使用数百个 session_name,但对于任何给定的测试,我最多只有少数几个会话。因此,一个好的解决方案重用吵闹会话,但让我在每次测试运行时使用任意会话名称。
规范/实用程序.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
Run Code Online (Sandbox Code Playgroud)
在 *spec_helper.rb* 中:
config.after(:each) do
Capybara.reset_sessions!
reset_session_mapper
end
Run Code Online (Sandbox Code Playgroud)
直接使用 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
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
1938 次 |
| 最近记录: |