当 运行 RSpec 测试时,从 Ruby 调用 shell 命令挂起
Calling a shell command from Ruby hangs when running RSpec test
以下情况会产生预期结果:
从 zsh,执行:
/usr/local/bin/pg_dump mydatabase #=> a bunch of sql output
从 irb 或 rails 控制台,执行:
`/usr/local/bin/pg_dump my_database` #=> a bunch of sql output
从一个方法中调用相同的 shell 命令:
class AppDb
def contents
`/usr/local/bin/pg_dump my_database`
end
end
# from rails console:
AppDb.new.contents #=> a bunch of sql stuff
但是,当我从 Rspec 测试完全相同的 AppDb class 时,shell 命令在断言处无限期挂起:
expect(AppDb.new.contents).to match "PostgreSQL database dump complete"
你知道为什么会这样吗?
挂起是由于:
spec_helper.rb
中的rspec配置
config.use_transactional_fixtures = 真
这会启动一个 postgresql BEGIN 块,它会启动对表的锁定
结合使用pg_dump,由于数据库锁无法执行。它挂起(永远或指定的超时)等待删除锁。
所以解决方案就是将 use_transactional_fixtures 设置为 false。当然,这会在规范末尾留下带有测试数据的数据库,必须以另一种方式处理。 DatabaseCleaner可以用,但是不能用事务策略,因为这样也会有同样的问题。
以下情况会产生预期结果:
从 zsh,执行:
/usr/local/bin/pg_dump mydatabase #=> a bunch of sql output
从 irb 或 rails 控制台,执行:
`/usr/local/bin/pg_dump my_database` #=> a bunch of sql output
从一个方法中调用相同的 shell 命令:
class AppDb def contents `/usr/local/bin/pg_dump my_database` end end # from rails console: AppDb.new.contents #=> a bunch of sql stuff
但是,当我从 Rspec 测试完全相同的 AppDb class 时,shell 命令在断言处无限期挂起:
expect(AppDb.new.contents).to match "PostgreSQL database dump complete"
你知道为什么会这样吗?
挂起是由于:
spec_helper.rb
中的rspec配置config.use_transactional_fixtures = 真
这会启动一个 postgresql BEGIN 块,它会启动对表的锁定
结合使用pg_dump,由于数据库锁无法执行。它挂起(永远或指定的超时)等待删除锁。
所以解决方案就是将 use_transactional_fixtures 设置为 false。当然,这会在规范末尾留下带有测试数据的数据库,必须以另一种方式处理。 DatabaseCleaner可以用,但是不能用事务策略,因为这样也会有同样的问题。