Подтвердить что ты не робот

Как проверить ElasticSearch в приложении Rails (Rspec)

Мне было интересно, как вы тестировали поиск в своем приложении при использовании ElasticSearch и Tire.

  • Как настроить новый тестовый экземпляр ElasticSearch? Есть ли способ издеваться над этим?

  • Любые драгоценные камни, которые вы знаете об этом, могут помочь с этим?


Некоторые вещи, которые я нашел полезными:

Я нашел замечательную статью, отвечающую почти на все мои вопросы:)

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

Кроме того, есть ответ от автора Karmi, автора Tire.

Это полезно также: https://github.com/karmi/tire/wiki/Integration-Testing-Rails-Models-with-Tire

Я не могу поверить, что не нашел их, прежде чем спрашивать...

4b9b3361

Ответ 1

Префикс ваших имен индексов для текущей среды

Вы можете установить другое имя-индекс для каждой среды (в вашем случае: тестовая среда).

Например, вы можете создать инициализатор в

config/initializers/tire.rb

со следующей строкой:

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

Возможный подход для удаления индексов

Предполагая, что у вас есть модели с именем Customer, Order и Product, поставьте следующий код где-нибудь в вашем тестовом запуске/перед блоком/каждым блоком.

# 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

Альтернативой может быть установка другого экземпляра ElasticSearch для тестирования на другом порту, скажем, 1234. В вашем enviornment/test.rb вы можете установить

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

И в подходящем месте (например, при запуске тестирования) вы можете удалить все индексы в экземпляре тестирования ElasticSearch с помощью

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

Может быть, вы все равно должны убедиться, что ваши определения Tire-Mapping для классов модели по-прежнему вызываются.

Ответ 2

Я столкнулся с причудливой ошибкой при удалении индекса elasticsearch через шину в моем пакете 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

Медиа - это мой модельный класс.

Ответ 3

Я столкнулся с подобными проблемами, и вот как я это решил. Не забывайте, что мое решение основывается на решении @spaudanjo. Поскольку я использую spork, я добавляю это внутри блока spec_helper.rb Spork.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

Он в основном определяет собственный собственный префикс для каждого тестового примера, чтобы в индексе не было. Остальные решения пострадали от проблемы, когда даже после удаления индекса 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. Результатом будет ваше название проекта.