rspec-solr 0.1.0 → 0.1.2
Sign up to get free protection for your applications and to get access to all the features.
- data/.yardopts +3 -0
- data/{expectation_matchers.rdoc → MATCHERS.rdoc} +8 -6
- data/README.rdoc +118 -3
- data/lib/rspec-solr/solr_response_hash.rb +7 -1
- data/lib/rspec-solr/version.rb +1 -1
- data/lib/tasks/doc.rake +1 -1
- data/rspec-solr.gemspec +1 -1
- data/spec/include_document_spec.rb +41 -7
- metadata +7 -6
data/.yardopts
ADDED
@@ -44,25 +44,26 @@
|
|
44
44
|
To change the id field name, use my_solr_response_hash.id_field='my_id_fldname'
|
45
45
|
===== Hash
|
46
46
|
* ("fldname" => "value")
|
47
|
-
* ("
|
48
|
-
|
49
|
-
|
47
|
+
* ("fldname" => /regex_to_match_val/)
|
48
|
+
* ("fld1" => "val1", "fld2" => /val2_regex/)
|
49
|
+
NOTE: single Solr document must satisfy all key value pairs
|
50
|
+
* ("fldname" => ["val1", /val2_regex/, "val3"])
|
50
51
|
NOTE: all of the Array values must be present for the fld in a single Solr document
|
51
52
|
should_not for Array implies NONE of the values should be present in a single document
|
52
53
|
TODO:
|
53
|
-
* document("fldname" => "/regex/")
|
54
54
|
* include_title("val") (i.e. include_anyFieldName("val") )
|
55
55
|
|
56
56
|
==== Specifying Multiple Documents
|
57
57
|
===== Array
|
58
58
|
* by id strings: (["id1", "id2", "id3"])
|
59
|
-
* by hashes: ([{"title" => "green is best"}, {"title" =>
|
59
|
+
* by hashes: ([{"title" => "green is best"}, {"title" => /blue/}, {"fld" => "val"}])
|
60
60
|
NOTE: you cannot do this: ([{"title" => ["Solr doc 1 title", "Solr doc 2 title"]} ]) to specify multiple documents
|
61
61
|
* by mix of id strings and hashes: ([{"title" => "green is best"}, "id3", {"author" => "steinbeck"}])
|
62
62
|
|
63
63
|
==== Full Examples
|
64
64
|
* rspec-solr_resp_hash.should include("fld1" => "val1")
|
65
|
-
* rspec-solr_resp_hash.should include("
|
65
|
+
* rspec-solr_resp_hash.should include("fld1" => /regex_for_val/)
|
66
|
+
* rspec-solr_resp_hash.should include("f1" => "v1", "f2" => ["val1", "val2", /regex_for_val/])
|
66
67
|
* rspec-solr_resp_hash.should include("idval")
|
67
68
|
* rspec-solr_resp_hash.should include(["id1", "id2", "id3"])
|
68
69
|
* rspec-solr_resp_hash.should include([{"title" => "title1"}, {"title" => "title2"}])
|
@@ -85,6 +86,7 @@ TODO:
|
|
85
86
|
|
86
87
|
TODO:
|
87
88
|
* include_at_least(3).of_these_documents().in_first(3).results
|
89
|
+
* start_with()
|
88
90
|
|
89
91
|
=== Usage
|
90
92
|
See above for information on how to specify specific documents
|
data/README.rdoc
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
|
3
3
|
{<img src="https://secure.travis-ci.org/sul-dlss/rspec-solr.png?branch=master" alt="Build Status" />}[http://travis-ci.org/sul-dlss/rspec-solr]
|
4
4
|
|
5
|
-
|
5
|
+
A Gem to provide RSpec custom matchers to be used with Solr response objects.
|
6
6
|
|
7
7
|
== Installation
|
8
8
|
|
@@ -20,11 +20,122 @@ Or install it yourself as:
|
|
20
20
|
|
21
21
|
== Usage
|
22
22
|
|
23
|
-
See
|
23
|
+
See MATCHERS.rdoc for syntax of supported expectations.
|
24
|
+
|
25
|
+
=== Examples:
|
26
|
+
|
27
|
+
it "q of 'Buddhism' should get 8,500-10,500 results" do
|
28
|
+
resp = solr_resp_doc_ids_only({'q'=>'Buddhism'})
|
29
|
+
resp.should have_at_least(8500).documents
|
30
|
+
resp.should have_at_most(10500).documents
|
31
|
+
end
|
32
|
+
|
33
|
+
it "q of 'Two3' should have excellent results", :jira => 'VUF-386' do
|
34
|
+
resp = solr_resp_doc_ids_only({'q'=>'Two3'})
|
35
|
+
resp.should have_at_most(10).documents
|
36
|
+
resp.should include("5732752").as_first_result
|
37
|
+
resp.should include("8564713").in_first(2).results
|
38
|
+
resp.should_not include("5727394")
|
39
|
+
resp.should have_the_same_number_of_results_as(solr_resp_doc_ids_only({'q'=>'two3'}))
|
40
|
+
resp.should have_fewer_results_than(solr_resp_doc_ids_only({'q'=>'two 3'}))
|
41
|
+
end
|
42
|
+
|
43
|
+
it "Traditional Chinese chars 三國誌 should get the same results as simplified chars 三国志" do
|
44
|
+
resp = solr_resp_doc_ids_only({'q'=>'三國誌'})
|
45
|
+
resp.should have_at_least(240).documents
|
46
|
+
resp.should have_the_same_number_of_results_as(solr_resp_doc_ids_only({'q'=>'三国志'}))
|
47
|
+
end
|
48
|
+
|
49
|
+
=== How Do I Do That?
|
50
|
+
|
51
|
+
Essentially, you write a bunch of specs that
|
52
|
+
* send a request to your Solr index
|
53
|
+
* wrap the Solr Ruby response into the RSpecSolr::SolrResponseHash (blah = RSpecSolr::SolrResponseHash.new(orig_resp))
|
54
|
+
* utilize the matchers (blah.should have_document("222")) -- see MATCHERS.rdoc
|
55
|
+
|
56
|
+
There is an exemplar project utilizing rspec-solr at https://github.com/sul-dlss/sw_index_tests.
|
57
|
+
|
58
|
+
Besides the specs themselves, it has essentially 4 files to smooth the way.
|
59
|
+
|
60
|
+
==== 1. Gemfile
|
61
|
+
Indicate the required gems for bundler
|
62
|
+
|
63
|
+
source :rubygems
|
64
|
+
|
65
|
+
gem 'RedCloth' # for textile formatting used in Readme
|
66
|
+
gem 'rake'
|
67
|
+
gem 'rsolr' # for sending requests to and getting responses from solr
|
68
|
+
gem 'rspec-solr' # for rspec assertions against solr response object
|
69
|
+
|
70
|
+
==== 2. Rakefile
|
71
|
+
Make it easy to run various groups of specs from the command line
|
72
|
+
|
73
|
+
require 'rspec/core/rake_task'
|
74
|
+
|
75
|
+
desc "run specs expected to pass"
|
76
|
+
RSpec::Core::RakeTask.new(:rspec) do |spec|
|
77
|
+
spec.rspec_opts = ["-c", "-f progress", "-r ./spec/spec_helper.rb"]
|
78
|
+
end
|
79
|
+
|
80
|
+
==== 3. config/solr.yml
|
81
|
+
Your Solr base url goes here
|
82
|
+
|
83
|
+
test:
|
84
|
+
:url: http://your_solr_baseurl
|
85
|
+
|
86
|
+
dev:
|
87
|
+
:url: http://your_solr_baseurl
|
88
|
+
|
89
|
+
==== 4. spec/spec_helper.rb
|
90
|
+
Do a one time setup of Solr connection, and methods to make it easier to make desired Solr requests
|
91
|
+
|
92
|
+
require "yaml"
|
93
|
+
require 'rsolr'
|
94
|
+
|
95
|
+
$LOAD_PATH.unshift(File.dirname(__FILE__))
|
96
|
+
|
97
|
+
RSpec.configure do |config|
|
98
|
+
# FIXME: hardcoded yml group
|
99
|
+
solr_config = YAML::load_file('config/solr.yml')["test"]
|
100
|
+
@@solr = RSolr.connect(solr_config)
|
101
|
+
puts "Solr URL: #{@@solr.uri}"
|
102
|
+
end
|
103
|
+
|
104
|
+
# send a GET request to the default Solr request handler with the indicated Solr parameters
|
105
|
+
# @param solr_params [Hash] the key/value pairs to be sent to Solr as HTTP parameters, in addition to
|
106
|
+
# those to get only id fields and no facets in the response
|
107
|
+
# @return [RSpecSolr::SolrResponseHash] object for rspec-solr testing the Solr response
|
108
|
+
def solr_resp_doc_ids_only(solr_params)
|
109
|
+
solr_response(solr_params.merge(@@doc_ids_only))
|
110
|
+
end
|
111
|
+
|
112
|
+
private
|
113
|
+
|
114
|
+
# send a GET request to the indicated Solr request handler with the indicated Solr parameters
|
115
|
+
# @param solr_params [Hash] the key/value pairs to be sent to Solr as HTTP parameters
|
116
|
+
# @param req_handler [String] the pathname of the desired Solr request handler (defaults to 'select')
|
117
|
+
# @return [RSpecSolr::SolrResponseHash] object for rspec-solr testing the Solr response
|
118
|
+
def solr_response(solr_params, req_handler='select')
|
119
|
+
RSpecSolr::SolrResponseHash.new(@@solr.send_and_receive(req_handler, {:method => :get, :params => solr_params}))
|
120
|
+
end
|
121
|
+
|
122
|
+
# use these Solr HTTP params to reduce the size of the Solr responses
|
123
|
+
# response documents will only have id fields, and there will be no facets in the response
|
124
|
+
# @return [Hash] Solr HTTP params to reduce the size of the Solr responses
|
125
|
+
def doc_ids_only
|
126
|
+
{'fl'=>'id', 'facet'=>'false'}
|
127
|
+
end
|
128
|
+
|
24
129
|
|
25
130
|
== Ruby Version Compatibility
|
26
131
|
|
27
|
-
This should work with various rubies 1.8.7, but currently some tests expected ordered hashes (though the code itself doesn't require them).
|
132
|
+
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).
|
133
|
+
|
134
|
+
== Contribute
|
135
|
+
|
136
|
+
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 ...
|
137
|
+
|
138
|
+
Please share yours!
|
28
139
|
|
29
140
|
== Contributing
|
30
141
|
|
@@ -33,3 +144,7 @@ This should work with various rubies 1.8.7, but currently some tests expected or
|
|
33
144
|
3. Commit your changes (`git commit -am 'Added some feature'`)
|
34
145
|
4. Push to the branch (`git push origin my-new-feature`)
|
35
146
|
5. Create new Pull Request
|
147
|
+
|
148
|
+
== Releases
|
149
|
+
- in progress ... 0.1.1 improve README
|
150
|
+
- <b>0.1.0</b> Initial release
|
@@ -36,6 +36,7 @@ class RSpecSolr
|
|
36
36
|
# @example expected_doc Array
|
37
37
|
# ["1", "2", "3"] implies we expect Solr docs with ids 1, 2, 3 included in this response
|
38
38
|
# [{"title" => "warm fuzzies"}, {"title" => "cool fuzzies"}] implies we expect at least one Solr doc in this response matching each Hash in the Array
|
39
|
+
# [{"title" => /rm fuzz/}, {"title" => /^cool/}] implies we expect at least one Solr doc in this response matching each Hash in the Array
|
39
40
|
# @param [FixNum] max_doc_position maximum acceptable position (1-based) of document in results. (e.g. if 2, it must be the 1st or 2nd doc in the results)
|
40
41
|
def has_document?(expected_doc, max_doc_position = nil)
|
41
42
|
if expected_doc.is_a?(Hash)
|
@@ -47,7 +48,12 @@ class RSpecSolr
|
|
47
48
|
# if it's an Array, then all expected values must be present
|
48
49
|
Array(exp_vals).all? { | exp_val |
|
49
50
|
# a doc's fld values can be a String or an Array
|
50
|
-
|
51
|
+
case exp_val
|
52
|
+
when Regexp
|
53
|
+
Array(doc[exp_fname]).any? { |val| val =~ exp_val }
|
54
|
+
else
|
55
|
+
Array(doc[exp_fname]).include?(exp_val)
|
56
|
+
end
|
51
57
|
} &&
|
52
58
|
# satisfy doc's position in the results
|
53
59
|
(max_doc_position ? docs.find_index(doc) < max_doc_position : true)
|
data/lib/rspec-solr/version.rb
CHANGED
data/lib/tasks/doc.rake
CHANGED
@@ -11,7 +11,7 @@ begin
|
|
11
11
|
yt.options = ['--output-dir', doc_dest_dir,
|
12
12
|
'--readme', 'README.rdoc',
|
13
13
|
'--title', 'RSpec-Solr Documentation',
|
14
|
-
'--files', '
|
14
|
+
'--files', 'MATCHERS.rdoc']
|
15
15
|
end
|
16
16
|
rescue LoadError
|
17
17
|
desc "Generate YARD Documentation"
|
data/rspec-solr.gemspec
CHANGED
@@ -11,7 +11,7 @@ Gem::Specification.new do |gem|
|
|
11
11
|
gem.summary = "RSpec custom matchers for Solr response objects"
|
12
12
|
gem.homepage = "http://github.com/sul-dlss/rspec-solr"
|
13
13
|
|
14
|
-
gem.extra_rdoc_files = ["LICENSE.txt", "README.rdoc", "
|
14
|
+
gem.extra_rdoc_files = ["LICENSE.txt", "README.rdoc", "MATCHERS.rdoc"]
|
15
15
|
gem.files = `git ls-files`.split($\)
|
16
16
|
gem.test_files = gem.files.grep(%r{^spec/})
|
17
17
|
gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
|
@@ -93,8 +93,7 @@ describe RSpecSolr do
|
|
93
93
|
it "passes if no part of the expectatio is met" do
|
94
94
|
@solr_resp_5_docs.should_not include("id" => "not_there", "not_there" => "anything")
|
95
95
|
end
|
96
|
-
end # should_not include('fld1'=>'val1', 'fld2'=>'val2')
|
97
|
-
|
96
|
+
end # should_not include('fld1'=>'val1', 'fld2'=>'val2')
|
98
97
|
|
99
98
|
context "multi-valued fields and expectations" do
|
100
99
|
|
@@ -285,7 +284,7 @@ describe RSpecSolr do
|
|
285
284
|
|
286
285
|
context "should include(Array_of_Hashes)" do
|
287
286
|
it "passes if all Hashes in Array match all Solr documents in the response" do
|
288
|
-
@solr_resp_5_docs.should include([{"id"=>"111", "fld"
|
287
|
+
@solr_resp_5_docs.should include([{"id"=>"111", "fld"=>/val/, "fld2"=>"val2"},
|
289
288
|
{"id"=>"222"},
|
290
289
|
{"id"=>"333", "fld"=>"val"},
|
291
290
|
{"id"=>"444", "fld"=>["val1", "val2", "val3"]},
|
@@ -361,11 +360,46 @@ describe RSpecSolr do
|
|
361
360
|
|
362
361
|
context "regex value" do
|
363
362
|
|
364
|
-
context
|
365
|
-
it "
|
366
|
-
|
363
|
+
context "should include('fld' => /regex/)" do
|
364
|
+
it "passes if Solr document in response matches regex in named field" do
|
365
|
+
@solr_resp_5_docs.should include("id" => /\d{3}/)
|
366
|
+
@solr_resp_5_docs.should include("fld" => /^va/) # 2 docs match
|
367
367
|
end
|
368
|
-
|
368
|
+
it "passes if single value expectation is expressed as an Array" do
|
369
|
+
@solr_resp_5_docs.should include("id" => [/111/])
|
370
|
+
end
|
371
|
+
it "fails if no Solr document in response has 'fldval' for the named field" do
|
372
|
+
lambda {
|
373
|
+
@solr_resp_5_docs.should include("id" => /not there/)
|
374
|
+
}.should fail_matching('} to include {"id"=>/not there/}')
|
375
|
+
end
|
376
|
+
it "fails if no Solr document in response has the named field" do
|
377
|
+
lambda {
|
378
|
+
@solr_resp_5_docs.should include("not_there" => /anything/)
|
379
|
+
}.should fail_matching('} to include {"not_there"=>/anything/}')
|
380
|
+
end
|
381
|
+
end # should include('fld' => /regex/)
|
382
|
+
|
383
|
+
context "should_NOT include('fld' => /regex/)" do
|
384
|
+
it "fails if Solr document in response matches regex in named field" do
|
385
|
+
lambda {
|
386
|
+
@solr_resp_5_docs.should_not include("id" => /\d{3}/)
|
387
|
+
}.should fail_matching('not to include {"id"=>/\d{3}/}')
|
388
|
+
lambda {
|
389
|
+
@solr_resp_5_docs.should_not include("fld" => /^va/)
|
390
|
+
}.should fail_matching('not to include {"fld"=>/^va/}')
|
391
|
+
end
|
392
|
+
it "passes if no Solr document in response has 'fldval' for the named field" do
|
393
|
+
@solr_resp_5_docs.should_not include({"id" => /not there/})
|
394
|
+
end
|
395
|
+
it "passes if no Solr document in response has the named field" do
|
396
|
+
@solr_resp_5_docs.should_not include({"not_there" => /anything/})
|
397
|
+
end
|
398
|
+
it "passes if single field value is expressed as Array" do
|
399
|
+
@solr_resp_5_docs.should_not include({"id" => [/not there/]})
|
400
|
+
end
|
401
|
+
|
402
|
+
end # should_NOT include('fld' => /regex/)
|
369
403
|
|
370
404
|
end # regex value
|
371
405
|
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rspec-solr
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.2
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -10,7 +10,7 @@ authors:
|
|
10
10
|
autorequire:
|
11
11
|
bindir: bin
|
12
12
|
cert_chain: []
|
13
|
-
date: 2012-
|
13
|
+
date: 2012-10-16 00:00:00.000000000 Z
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: rspec
|
@@ -133,16 +133,17 @@ extensions: []
|
|
133
133
|
extra_rdoc_files:
|
134
134
|
- LICENSE.txt
|
135
135
|
- README.rdoc
|
136
|
-
-
|
136
|
+
- MATCHERS.rdoc
|
137
137
|
files:
|
138
138
|
- .gitignore
|
139
139
|
- .rvmrc
|
140
140
|
- .travis.yml
|
141
|
+
- .yardopts
|
141
142
|
- Gemfile
|
142
143
|
- LICENSE.txt
|
144
|
+
- MATCHERS.rdoc
|
143
145
|
- README.rdoc
|
144
146
|
- Rakefile
|
145
|
-
- expectation_matchers.rdoc
|
146
147
|
- lib/rspec-solr.rb
|
147
148
|
- lib/rspec-solr/compare_num_docs_matcher.rb
|
148
149
|
- lib/rspec-solr/have_documents_matcher.rb
|
@@ -176,7 +177,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
176
177
|
version: '0'
|
177
178
|
segments:
|
178
179
|
- 0
|
179
|
-
hash:
|
180
|
+
hash: -4597988063406856522
|
180
181
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
181
182
|
none: false
|
182
183
|
requirements:
|
@@ -185,7 +186,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
185
186
|
version: '0'
|
186
187
|
segments:
|
187
188
|
- 0
|
188
|
-
hash:
|
189
|
+
hash: -4597988063406856522
|
189
190
|
requirements: []
|
190
191
|
rubyforge_project:
|
191
192
|
rubygems_version: 1.8.24
|