RSpec Solr
A Gem to provide RSpec custom matchers to be used with Solr response objects.
Installation
Add this line to your application's Gemfile:
gem 'rspec-solr'
And then execute:
$ bundle
Or install it yourself as:
$ gem install rspec-solr
Usage
See MATCHERS.md
for syntax of supported expectations.
Examples:
it "q of 'Buddhism' should get 8,500-10,500 results" do
resp = solr_resp_doc_ids_only({'q'=>'Buddhism'})
resp.should have_at_least(8500).documents
resp.should have_at_most(10500).documents
end
it "q of 'Two3' should have excellent results", :jira => 'VUF-386' do
resp = solr_response({'q'=>'Two3', 'fl'=>'id', 'facet'=>false})
resp.should have_at_most(10).documents
resp.should include("5732752").as_first_result
resp.should include("8564713").in_first(2).results
resp.should_not include("5727394")
resp.should have_the_same_number_of_results_as(solr_resp_doc_ids_only({'q'=>'two3'}))
resp.should have_fewer_results_than(solr_resp_doc_ids_only({'q'=>'two 3'}))
end
it "Traditional Chinese chars 三國誌 should get the same results as simplified chars 三国志" do
resp = solr_response({'q'=>'三國誌', 'fl'=>'id', 'facet'=>false})
resp.should have_at_least(240).documents
resp.should have_the_same_number_of_results_as(solr_resp_doc_ids_only({'q'=>'三国志'}))
end
How Do I Do That?
Essentially, you write a bunch of specs that
- send a request to your Solr index
- wrap the Solr Ruby response into the
RSpecSolr::SolrResponseHash
(`blah = RSpecSolr::SolrResponseHash.new(orig_resp)``) - utilize the matchers (
expect(blah).to have_document("222")``) -- see
MATCHERS.md`
There is an exemplar project utilizing rspec-solr at https://github.com/sul-dlss/sw_index_tests.
Besides the specs themselves, it has essentially 4 files to smooth the way.
1. Gemfile
Indicate the required gems for bundler
gem 'rsolr' # for sending requests to and getting responses from solr
gem 'rspec-solr' # for rspec assertions against solr response object
2. Rakefile
Make it easy to run various groups of specs from the command line
require 'rspec/core/rake_task'
desc "run specs expected to pass"
RSpec::Core::RakeTask.new(:rspec) do |spec|
spec.rspec_opts = ["-c", "-f progress", "-r ./spec/spec_helper.rb"]
end
3. config/solr.yml
Your Solr base url goes here
test:
:url: http://your_solr_baseurl
dev:
:url: http://your_solr_baseurl
4. spec/spec_helper.rb
Do a one time setup of Solr connection, and methods to make it easier to make desired Solr requests
require "yaml"
require 'rsolr'
$LOAD_PATH.unshift(File.dirname(__FILE__))
RSpec.configure do |config|
# FIXME: hardcoded yml group
solr_config = YAML::load_file('config/solr.yml')["test"]
@@solr = RSolr.connect(solr_config)
puts "Solr URL: #{@@solr.uri}"
end
private
# send a GET request to the indicated Solr request handler with the indicated Solr parameters
# @param solr_params [Hash] the key/value pairs to be sent to Solr as HTTP parameters
# @param req_handler [String] the pathname of the desired Solr request handler (defaults to 'select')
# @return [RSpecSolr::SolrResponseHash] object for rspec-solr testing the Solr response
def solr_response(solr_params, req_handler='select')
RSpecSolr::SolrResponseHash.new(@@solr.send_and_receive(req_handler, {:method => :get, :params => solr_params}))
end
4a. a little more magic
You might want to add code such as that below to your spec_helper - it can help keep your solr responses small, which makes for easier debugging.
# send a GET request to the default Solr request handler with the indicated Solr parameters
# @param solr_params [Hash] the key/value pairs to be sent to Solr as HTTP parameters, in addition to
# those to get only id fields and no facets in the response
# @return [RSpecSolr::SolrResponseHash] object for rspec-solr testing the Solr response
def solr_resp_doc_ids_only(solr_params)
solr_response(solr_params.merge(@@doc_ids_only))
end
# use these Solr HTTP params to reduce the size of the Solr responses
# response documents will only have id fields, and there will be no facets in the response
# @return [Hash] Solr HTTP params to reduce the size of the Solr responses
def doc_ids_only
{'fl'=>'id', 'facet'=>'false'}
end
Contribute
I'm currently envisioning helper methods shared somehow - either on the github wikis, or in this gem as exemplars, or in a separate gem, or ...
Please share yours!
Contributing
- Fork it
- Create your feature branch (
git checkout -b my-new-feature
) - Commit your changes (
git commit -am 'Added some feature'
) - Push to the branch (
git push origin my-new-feature
) - Create new Pull Request
Releases
- 3.0.0 Add compatibility with rspec ~> 3.5
- 2.0.0 No release notes
- 1.0.1 fix spec failing in travis due to diff error message in later rspec version
- 1.0.0 declare victory and make 0.2.0 into 1.0.0
- 0.2.0 add facet support have_facet_field(fld_name).with_value(fld_value)
- 0.1.4 fix regex match to work with in_each_of_first(n)
- 0.1.3 added include().in_each_of_first(n)
- 0.1.2 added document matching via regex for field values
- 0.1.1 improve README
- 0.1.0 Initial release