luc*_*ins 12 ruby rspec ruby-on-rails elasticsearch
我有一个带有Rspec测试套件的Rails应用程序,它具有一些功能/控制器测试,具体取决于ElasticSearch.
当我们测试系统周围的"搜索"功能(以及依赖于ES的其他功能)时,我们使用真正的ES,当我们运行单个spec文件时,它在开发环境中完美运行.
当套件在我们的CI服务器上运行时,它变得很奇怪,因为有时 ES不会保持同步足够快以使测试成功运行.
我已经搜索了一些在"同步模式"下运行ES的方法,或者等到ES准备好但到目前为止还没找到任何东西.我见过一些使用Ruby的变通方法,sleep但我觉得这是不可接受的.
我怎样才能保证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
Run Code Online (Sandbox Code Playgroud)
这是我的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
Run Code Online (Sandbox Code Playgroud)
谢谢你的帮助!
您的测试很困惑 - 它正在测试分配,分页和(隐式)参数传递.打破它:
参数
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
Run Code Online (Sandbox Code Playgroud)
分配
我们只担心代码占用一个值并将其分配给其他值,这个值是无关紧要的.
it 'assigns the search results to companies' do
Companies.stub(:tire).with(tire)
get :index, params
expect(assigns[:companies]).to eq :sentinel
end
Run Code Online (Sandbox Code Playgroud)
分页
这是棘手的一点.您不拥有ES API,因此您不应该使用它,但您也不能使用ES的实例,因为您不能相信它在所有测试场景中都是可靠的,它只是一个HTTP API之后所有(这是你所拥有的根本问题).Gary Bernhardt在他的一个优秀的截屏视频中解决了这个问题- 你只需要伪造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
Run Code Online (Sandbox Code Playgroud)
成功运行一次然后永远更多地使用盒式磁带(这只是响应的YAML文件).您的测试不再依赖于您无法控制的API.如果ES或您的分页宝石更新其代码,只需在您知道API已启动并正常工作时重新录制磁带.没有任何其他选择,如果你的测试非常脆弱,或者你不应该存根.
请注意,虽然我们tire上面已经存在- 而且我们没有它 - 但在这些情况下它是正常的,因为返回值与测试完全无关.
| 归档时间: |
|
| 查看次数: |
929 次 |
| 最近记录: |