0

我正在编写一个 Rails 系统,它通过生成多个进程来获取数据并更新单个数据库表来从外部源获取数据。我想编写 RSpec 测试来生成多个进程,这些进程模拟 fetch/write 进程以查找并发问题。

简短的问题

如何在 RSpec 测试中初始化表,以便外部进程可以看到表的内容?(至少,我认为这是正确的问题。请继续阅读以了解详细信息......)

较长的形式

我的 RSpec 测试的一般结构是:

it 'external task should update the correct records' do
  initialize_my_model_table_with_some_records
  spawn_external_tasks_to_update_records
  # wait for spawned processes to complete
  Process.waitall.each {|pid, status| status.exitstatus.should == 0 }
  validate_results
end

但是外部进程总是将模型表视为空的(通过调试打印验证)。随后,尝试更新表失败。

我很确定这是因为 RSpec 将表置于锁定状态,因此它可以在测试完成后进行回滚。

所以(重复这个简短的问题):如何在 RSpec 测试中初始化表,以便外部进程可以看到表的初始化内容?

编辑#2

我注意到在进入后续测试时,该表处于先前(外部)进程离开它的状态。这是有道理的:RSpec 只能将表回滚到它“知道”的状态,因此外部进程所做的更改将持续存在。

这提出了一个解决方案:似乎可以使用 before(:all) 显式初始化表。但这是最干净的方法吗?

环境

  • Ruby 版本 1.9.3 (x86_64-darwin10.8.0)
  • 皮克(0.13.2)
  • 导轨 (3.2.1)
  • rspec (2.9.0)
  • rspec-rails (2.9.0)
4

1 回答 1

0

当 RSpec 运行测试时,它会将数据库锁定在事务下,以便在测试后可以回滚。因此,任何外部进程都不会看到 RSpec 对数据库所做的更改。相应地,外部进程对数据库所做的任何更改都不会在 RSpec 测试后回滚。

一个例外是内部before(:all)after(:all)块:RSpec 所做的任何更改都将对外部进程可见。

所以OP中的例子可以这样工作:

describe 'with external tasks' do
  before(:all)
    initialize_my_model_table_with_some_records
  end
  after(:all)
    reinitialize_my_model_table
  end

  it 'should update the correct records' do
    spawn_external_tasks_to_update_records
    # wait for spawned processes to complete
    Process.waitall.each {|pid, status| status.exitstatus.should == 0 }
    validate_results
  end
end
于 2012-06-26T18:04:19.383 回答