I was wondering how you were testing the search in your application when using ElasticSearch and Tire.
How do you setup a new ElasticSearch test instance? 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
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
I can't believe I did not find these before asking...
To get it running: install all gems, create the database (SQLite 3), run an elasticsearch instance in the background and seed the Application with the provided Wikipedia articles within the /db/seed/ directory. After you've got it running go to localhost:3000 and try searching for ruby or language.
Running tests by their file or directory names is the most familiar way to run tests with RSpec. RSpec can take a file name or directory name and run the file or the contents of the directory. So you can do: rspec spec/jobs to run the tests found in the jobs directory.
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}"
Assuming that you have models named Customer, Order and Product, put the following code somewhere at your 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
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
Tire::Configuration.url "http://localhost:1234"
And at a suitable location (e.g. your testing startup) you can then delete all indexes on the ElasticSearch testing-instance with:
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. 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.
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).
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. Adding the create_elasticsearch_index call fixed the problem:
config.after(:each) do
DatabaseCleaner.clean
Media.tire.index.delete
Media.tire.create_elasticsearch_index
end
Media is my model class.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With