简体   繁体   English

如何在Rails应用程序中测试ElasticSearch(Rspec)

[英]How to test ElasticSearch in a Rails application (Rspec)

I was wondering how you were testing the search in your application when using ElasticSearch and Tire. 我想知道在使用ElasticSearch和Tire时如何在应用程序中测试搜索。

  • How do you setup a new ElasticSearch test instance? 您如何设置新的ElasticSearch测试实例? Is there a way to mock it? 有没有办法嘲笑它?

  • Any gems you know of that might help with that? 你知道的任何宝石可能对此有所帮助吗?


Some stuff I found helpful: 我发现一些有用的东西:

I found a great article answering pretty much all my questions :) 我发现了一篇很棒的文章回答了我所有的问题:)

http://bitsandbit.es/post/11295134047/unit-testing-with-tire-and-elastic-search#disqus_thread http://bitsandbit.es/post/11295134047/unit-testing-with-tire-and-elastic-search#disqus_thread

Plus, there is an answer from Karmi, Tire author. 此外,还有来自轮胎作者卡米的答案。

This is useful as well: https://github.com/karmi/tire/wiki/Integration-Testing-Rails-Models-with-Tire 这也很有用: https//github.com/karmi/tire/wiki/Integration-Testing-Rails-Models-with-Tire

I can't believe I did not find these before asking... 在问之前我无法相信我没有找到这些......

Prefixing your index-names for the current environment 为当前环境添加索引名称前缀

You could set a different index-name for each environment (in your case: the test environment). 您可以为每个环境设置不同的索引名称(在您的情况下:测试环境)。

For example, you could create an initializer in 例如,您可以在中创建初始化程序

config/initializers/tire.rb

with the following line: 使用以下行:

Tire::Model::Search.index_prefix "#{Rails.application.class.parent_name.downcase}_#{Rails.env.to_s.downcase}"

A conceivable approach for deleting the indexes 一种可以想到的删除索引的方法

Assuming that you have models named Customer, Order and Product, put the following code somewhere at your test-startup/before-block/each-run-block. 假设您有名为Customer,Order和Product的模型,请将以下代码放在test-startup / before-block / each-run-block的某处。

# iterate over the model types
# there are also ways to fetch all model classes of the rails app automaticly, e.g.:
#   http://stackoverflow.com/questions/516579/is-there-a-way-to-get-a-collection-of-all-the-models-in-your-rails-app
[Customer, Order, Product].each do |klass|

  # make sure that the current model is using tire
  if klass.respond_to? :tire
    # delete the index for the current model
    klass.tire.index.delete

    # the mapping definition must get executed again. for that, we reload the model class.
    load File.expand_path("../../app/models/#{klass.name.downcase}.rb", __FILE__)

  end
end

Alternative 替代

An alternative could be to set up a different ElasticSearch instance for testing on another port, let's say 1234. In your enviornment/test.rb you could then set 另一种方法是设置一个不同的ElasticSearch实例来测试另一个端口,比方说1234.在你的enviornment / test.rb中,你可以设置

Tire::Configuration.url "http://localhost:1234"

And at a suitable location (eg your testing startup) you can then delete all indexes on the ElasticSearch testing-instance with: 在适当的位置(例如您的测试启动),您可以删除ElasticSearch测试实例上的所有索引:

Tire::Configuration.client.delete(Tire::Configuration.url)

Maybe you must still make sure that your Tire-Mapping definitions for you model classes are still getting called. 也许您仍然必须确保您的模型类的轮胎映射定义仍然被调用。

I ran into a quirky bug when deleting my elasticsearch index via tire in my rspec suite. 在我的rspec套件中通过轮胎删除我的弹性搜索索引时遇到了一个奇怪的错误。 In my Rspec configuration, similar to the Bits and Bytes blog, I have an after_each call which cleans the database and wipes out the index. 在我的Rspec配置中,类似于Bits和Bytes博客,我有一个after_each调用,它清理数据库并清除索引。

I found I needed to call Tire's create_elasticsearch_index method which is responsible for reading the mapping in the ActiveRecord class to set up the appropriate analyzers, etc. The issue I was seeing was I had some :not_analyzed fields in my model which were actually getting analyzed (this broke how I wanted faceting to work). 我发现我需要调用Tire的create_elasticsearch_index方法,该方法负责读取ActiveRecord类中的映射以设置适当的分析器等。我看到的问题是我在我的模型中有一些:not_analyzed字段实际上正在分析(这打破了我想要分面工作的方式)。

Everything was fine on dev, but the test suite was failing as facets were being broken down by individual words and not the entire multi word string. 开发方面的一切都很好,但测试套件失败了,因为各个单词而不是整个多字符串都破坏了方面。 It seems that the mapping configuration was not being created appropriately in rspec after the index was deleted. 删除索引后,似乎没有在rspec中正确创建映射配置。 Adding the create_elasticsearch_index call fixed the problem: 添加create_elasticsearch_index调用修复了问题:

config.after(:each) do
  DatabaseCleaner.clean
  Media.tire.index.delete
  Media.tire.create_elasticsearch_index
end

Media is my model class. 媒体是我的模特课。

I ran into similar issues and here's how I solved it. 我遇到了类似的问题,这就是我解决它的方法。 Bare in mind that my solution builds on top of @spaudanjo solution. 请记住,我的解决方案建立在@spaudanjo解决方案之上。 Since I'm using spork, I add this inside the spec_helper.rb 's Spork.each_run block, but you may add this into any other each/before block. 由于我正在使用spork,我在spec_helper.rbSpork.each_run块中添加了这个,但是你可以将它添加到任何其他每个/之前的块中。

# Define random prefix to prevent indexes from clashing
Tire::Model::Search.index_prefix "#{Rails.application.class.parent_name.downcase}_#{Rails.env.to_s.downcase}_#{rand(1000000)}"

# In order to know what all of the models are, we need to load all of them
Dir["#{Rails.root}/app/models/**/*.rb"].each do |model|
  load model
end

# Refresh Elastic Search indexes
# NOTE: relies on all app/models/**/*.rb to be loaded
models = ActiveRecord::Base.subclasses.collect { |type| type.name }.sort
models.each do |klass|
  # make sure that the current model is using tire
  if klass.respond_to? :tire
    # delete the index for the current model
    klass.tire.index.delete

    # the mapping definition must get executed again. for that, we reload the model class.
    load File.expand_path("../../app/models/#{klass.name.downcase}.rb", __FILE__)
  end
end

It basically defines it's own unique prefix for every test case so that there are no in indexes. 它基本上为每个测试用例定义了它自己的唯一前缀,因此索引中没有。 The other solutions all suffered from a problem where even after deleting the index, Elastic Search wouldn't refresh the indexes (even after running Model.index.refresh ) which is why the randomized prefix is there. 其他解决方案都遇到了一个问题,即使在删除索引之后,Elastic Search也不会刷新索引(即使在运行Model.index.refresh ),这就是随机化前缀存在的原因。

It also loads every model and checks if it responds to tire so that we no longer need to maintain a list of all of the models that respond to tire both in spec_helper.rb and in other areas. 它还会加载每个模型并检查它是否响应tire以便我们不再需要维护在spec_helper.rb和其他区域中响应轮胎的所有模型的列表。

As this method doesn't "delete" the indexes after using it, you will have to manually delete it on a regular basis. 由于此方法在使用后不会“删除”索引,因此您必须定期手动删除它。 Though I don't imagine this to be a huge issue, you can delete with the following command: 虽然我不认为这是一个很大的问题,但您可以使用以下命令删除:

curl -XDELETE 'http://localhost:9200/YOURRAILSNAMEHERE_test_*/'

To find what YOURRAILSNAMEHERE is, run rails console and run Rails.application.class.parent_name.downcase . 要查找YOURRAILSNAMEHERE是什么,请运行rails console并运行Rails.application.class.parent_name.downcase The output will be your project's name. 输出将是您项目的名称。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM