RSpec Solr

Build Status Dependency Status

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.rdoc 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 (blah.should have_document(“222”)) – see MATCHERS.rdoc

There is an exemplar project utilizing rspec-solr at 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

source :rubygems

gem 'RedCloth' 		# for textile formatting used in Readme
gem 'rake'
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

Ruby Version Compatibility

This should work with various rubies 1.8.7, but currently some tests expected ordered hashes (though the code itself doesn't require them - just THIS gem's TEST code).

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

  1. Fork it

  2. Create your feature branch (`git checkout -b my-new-feature`)

  3. Commit your changes (`git commit -am 'Added some feature'`)

  4. Push to the branch (`git push origin my-new-feature`)

  5. Create new Pull Request

Releases

  • 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