调试 Rspec Postgres 锁定

问题描述 投票:0回答:2

我正在尝试测试一个使用

gem devise_token_auth
的应用程序,它基本上包括几乎每个请求的几个额外的数据库读/写(以验证和更新用户访问令牌)。

一切工作正常,除了测试包含多个额外数据库读/写的控制器操作时除外。在这些情况下,终端会锁定,我被迫通过活动监视器终止 ruby 进程。

有时我会收到这样的错误消息:

ruby /Users/evan/.rvm/gems/ruby-2.1.1/bin/rspec spec/controllers/api/v1/messages_controller_spec.rb(1245,0x7fff792bf310) malloc: *** error for object 0x7ff15fb73c00: pointer being freed was not allocated
*** set a breakpoint in malloc_error_break to debug
Abort trap: 6

我不知道如何解释这一点。我 90% 确信问题是由于这个 gem 以及它在每个请求上引起的额外数据库活动造成的,因为当我恢复到以前的、强度较低的身份验证时,所有问题都会消失。我还通过给 postgres 一些额外的时间来处理有问题的测试,让事情得到了控制:

after :each do
  sleep 2
end

这对于所有情况都适用,除了一种情况,这需要在

expect
之前超时,否则会抛出此错误:

Failure/Error: expect(@user1.received_messages.first.read?).to eq true
     ActiveRecord::StatementInvalid:
       PG::UnableToSend: another command is already in progress
       : SELECT  "messages".* FROM "messages"  WHERE "messages"."receiver_id" = $1  ORDER BY "messages"."id" ASC LIMIT 1

对我来说,这再次指向数据库问题。

我还可以做些什么来追踪/控制这些错误吗?我应该研究任何 rspec 设置吗?

ruby-on-rails postgresql rspec
2个回答
0
投票

如果您正在运行并行 rspec 任务,则可能会触发此问题。当我们遇到这样的问题时,我们会使用标签强制这些测试在 CI 中的单个非并行 rspec 实例中运行。

尝试这样的事情:

  context 'when both records get updated in one job', non_parallel do
    it { is_expected.to eq 2 }
  end

然后在 non_parallel 标签上单独调用 rspec:

  rspec --tag non_parallel

您的大部分测试(未标记为 non_parallel)仍然可以在 CI 解决方案(例如 Jenkins)中并行运行以提高性能。

当然,使用这个创可贴时要小心。最好确定代码中哪些内容不是竞争安全的,因为这种竞争可能在现实世界中发生。


0
投票

在其他方法失败的情况下(例如在其他答案中识别竞争问题),我建议获取源代码的新副本,启动一个新分支并开始删除导致错误发生的位。

这可能需要一些时间,但最终您将获得一个小的可重复测试用例,使您可以轻松地了解导致问题的确切原因。

首先,您可以使用类似

rspec --bisect
(或类似的测试工具)来获取复制命令,然后开始删除测试和 gem。

定期提交,最后删除您所在的分支。

如果问题是间歇性的,那么您会遇到更大的问题,但是阅读有关避免间歇性故障的技术可能会有所帮助。

© www.soinside.com 2019 - 2024. All rights reserved.