Search code examples
ruby-on-railspostgresqlrspecrspec-rails

Calling a shell command from Ruby hangs when running RSpec test


The following scenarios produce the expected results:

  1. from zsh, execute:

    /usr/local/bin/pg_dump mydatabase  #=> a bunch of sql output
    
  2. from irb or rails console, execute:

    `/usr/local/bin/pg_dump my_database` #=> a bunch of sql output
    
  3. Call the same shell command from within a method:

    class AppDb
      def contents
        `/usr/local/bin/pg_dump my_database`
      end
    end
    
    # from rails console:
    AppDb.new.contents #=> a bunch of sql stuff
    

However, when I test the very same AppDb class from Rspec, the shell command hangs indefinitely at the assertion:

expect(AppDb.new.contents).to match "PostgreSQL database dump complete"

Do you have any idea why this might be?


Solution

  • The hang is due to:

    1. the rspec configuration in spec_helper.rb

      config.use_transactional_fixtures = true

      This initiates a postgresql BEGIN block, which initiates locking on the tables

    2. in combination with the use of pg_dump, which cannot execute due to the database locks. It hangs (forever or for a specified timeout) waiting for the locks to be removed.

    So the solution is simply to set use_transactional_fixtures to false. Of course, this leaves the database with test data at the end of the spec, which must be handled another way. DatabaseCleaner can be used, but not with transaction strategy, as this will have the same problem.