46

我想知道您在使用 ElasticSearch 和 Tire 时如何在应用程序中测试搜索。

  • 如何设置新的 ElasticSearch 测试实例?有没有办法嘲笑它?

  • 您知道的任何宝石可能对此有所帮助吗?


我发现一些有用的东西:

我发现一篇很棒的文章回答了我几乎所有的问题:)

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

另外,还有来自轮胎作者 Karmi 的回答。

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

我不敢相信我在问之前没有找到这些......

4

3 回答 3

34

为当前环境添加索引名称的前缀

您可以为每个环境(在您的情况下:测试环境)设置不同的索引名称。

例如,您可以在

config/initializers/tire.rb

使用以下行:

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

删除索引的一种可能的方法

假设您有名为 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

选择

另一种方法是设置一个不同的 ElasticSearch 实例以在另一个端口上进行测试,比如 1234。然后在您的 enviornment/test.rb 中设置

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

然后在合适的位置(例如您的测试启动),您可以删除 ElasticSearch 测试实例上的所有索引:

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

也许您仍然必须确保您的模型类的轮胎映射定义仍然被调用。

于 2012-03-14T18:09:16.187 回答
11

在我的 rspec 套件中通过轮胎删除我的弹性搜索索引时遇到了一个奇怪的错误。在我的 Rspec 配置中,类似于 Bits and Bytes 博客,我有一个 after_each 调用来清理数据库并清除索引。

我发现我需要调用 Tire 的 create_elasticsearch_index 方法,该方法负责读取 ActiveRecord 类中的映射以设置适当的分析器等。我看到的问题是我的模型中有一些 :not_analyzed 字段实际上正在被分析(这打破了我想要刻面工作的方式)。

dev 上一切都很好,但是测试套件失败了,因为各个方面被单个单词而不是整个多单词字符串分解。删除索引后,似乎没有在 rspec 中正确创建映射配置。添加 create_elasticsearch_index 调用解决了这个问题:

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

媒体是我的模范课。

于 2012-05-04T15:27:42.303 回答
4

我遇到了类似的问题,这就是我解决它的方法。请记住,我的解决方案建立在@spaudanjo 解决方案之上。由于我使用的是 spork,因此我将其添加到spec_helper.rb'Spork.each_run块中,但您可以将其添加到任何其他 each/before 块中。

# 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

它基本上为每个测试用例定义了自己的唯一前缀,因此没有索引。其他解决方案都遇到了一个问题,即即使在删除索引之后,Elastic Search 也不会刷新索引(即使在运行之后Model.index.refresh),这就是随机前缀存在的原因。

它还加载每个模型并检查它是否响应,tire以便我们不再需要维护所有模型的列表,这些模型spec_helper.rb在其他区域和其他区域都对轮胎做出响应。

由于此方法在使用后不会“删除”索引,因此您必须定期手动删除它。虽然我不认为这是一个大问题,但您可以使用以下命令删除:

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

要找到是什么YOURRAILSNAMEHERE,运行rails console并运行Rails.application.class.parent_name.downcase。输出将是您的项目名称。

于 2013-03-02T12:21:32.753 回答