ruby-on-rails – 弹性搜索在测试套件上被HTTP覆盖时不同步

前端之家收集整理的这篇文章主要介绍了ruby-on-rails – 弹性搜索在测试套件上被HTTP覆盖时不同步前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
我有一个带Rspec测试套件的Rails应用程序,它具有一些功能/控制器测试,取决于ElasticSearch.

当我们测试系统周围的“搜索功能(以及依赖于ES的其他功能)时,我们使用了一个真正的ES,当我们运行单一的spec文件时,它在开发环境中工作得很好.

当套件在我们的CI服务器上运行时,它变得很奇怪,因为有时ES将不能保持足够的同步,以使测试成功运行.

搜索了某种方式以“syncronous模式”运行ES,或者等到ES准备好了,但到目前为止还没有找到任何东西.我已经看到使用Ruby睡眠的一些解决方法,但我觉得不能接受.

我如何保证ES同步运行我的测试?

你在测试套件上如何处理ES?

这是我的一个测试:

context "given params page or per_page is set",:elasticsearch do

      let(:params) { {query: "Resultados",page: 1,per_page: 2} }

      before(:each) do
        3.times do |n|
          Factory(:company,account: user.account,name: "Resultados Digitais #{n}")
        end
        sync_companies_index # this is a helper method available to all specs
      end

      it "paginates the results properly" do
        get :index,params
        expect(assigns[:companies].length).to eq 2
      end

    end

这是我的RSpec配置块和ES帮助方法

RSpec.configure do |config|
  config.around :each do |example|
    if example.Metadata[:elasticsearch]
      Lead.tire.index.delete # delete the index for a clean environment
      Company.tire.index.delete # delete the index for a clean environment

      example.run
    else
      FakeWeb.register_uri :any,%r(#{Tire::Configuration.url}),body: '{}'
      example.run
      FakeWeb.clean_registry
    end
  end
end

def sync_companies_index
  sync_index_of Company
end

def sync_leads_index
  sync_index_of Lead
end

def sync_index_of(klass)
  mapping = MultiJson.encode(klass.tire.mapping_to_hash,:pretty => Tire::Configuration.pretty)
  klass.tire.index.create(:mappings => klass.tire.mapping_to_hash,:settings => klass.tire.settings)
  "#{klass}::#{klass}Index".constantize.rebuild_index
  klass.index.refresh
end

感谢任何帮助!

解决方法

你的测试很困惑 – 它是测试分配,分页和(隐含)参数传递.打破它:

参数

let(:tire) { double('tire',:search => :sentinel) }

it 'passes the correct parameters to Companies.tire.search' do
  expected_params = ... # Some transformation,if any,of params
  Companies.stub(:tire).with(tire)
  get :index,params

  expect(tire).to have_received(:search).with(expected_params)
end

分配

我们只关心代码是取一个值并将其分配给别的东西,这个值是无关紧要的.

it 'assigns the search results to companies' do
  Companies.stub(:tire).with(tire)
  get :index,params

  expect(assigns[:companies]).to eq :sentinel
end

分页

这是棘手的一点.您不拥有ES API,因此您不应该存储它,但是您也不能使用ES的实时实例,因为您不能相信它在所有测试场景中都是可靠的,它只是一个HTTP API所有(这是你的根本问题).加里·伯恩哈特(Gary Bernhardt)在他出色的screencasts之一中解决了这个问题 – 您只需要虚构HTTP呼叫.使用录像机

VCR.use_cassette :tire_companies_search do
  get :index,params
  search_result_length = assigns[:companies].length

  expect(search_result_length).to eq 2
end

运行一次成功,然后永远更多地使用磁带(这只是一个YAML文件的响应).您的测试不再依赖于您无法控制的API.如果ES或您的分页宝石更新他们的代码,只需在您知道API正常工作时重新录制磁带.没有任何其他的选择,没有使您的测试非常脆弱或者存在你不应该存根的东西.

请注意,虽然我们已经把轮胎弄坏了,但我们并不拥有它 – 在这些情况下可以确定,因为返回值与测试完全无关.

猜你在找的Ruby相关文章