Posted by Patrick Baselier on 3-2-2010
We wanted to integrate the sunspot_rails gem into our cucumber features. I found a ticket where mat adviced to call Sunspot::Rails::Server.start / stop in one of the available cucumber hooks. Code found in features/support/env.rb is run when Cucumber begins and exits so this seemed the right place to start Solr:
1
2
3
4
5
Sunspot::Rails::Server.new.start
at_exit do
Sunspot::Rails::Server.new.stop
end
Also, make sure you’ve added a cucumber environment to the config/sunspot.yml file; we copied the test-environment for that:
1
2
3
4
5
6
7
8
test: &TEST
solr:
hostname: localhost
port: 8981
log_level: WARNING
cucumber:
<<: *TEST
Running cucumber will let all scenarios fail unfortunately and we got a ‘Connection refused - connect(2) (RSolr::RequestError)’ in our console. The reason for this is simple (after I stepped into the sunspot_rails gem to be honest): the Sunspot::Rails::Server.new.start method will eventually launch a Java Servlet Container (Jetty) with the Solr WAR and uses the port defined in your sunspot.yml. Now, starting up a server could take some time, so if cucumber’s features are run before the Solr server is up and running, the ‘Connection refused’ sounds trivial then. First I added a sleep after starting up the server:
1
2
Sunspot::Rails::Server.new.start
sleep(5)
and this will work for most cases, but I thought it would be better to let cucumber wait just long enough until the server is up and running. When the server is up, you can open up your browser and enter http://localhost:8981/solr to administering Solr. This we can use to find out if we’ve waited long enough and start our features. I’ve put this into a seperate class named CukeSunspot and created this file in the features/support directory:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
require "net/http"
class CukeSunspot
def initialize
@server = Sunspot::Rails::Server.new
end
def start
@started = Time.now
@server.start
up
end
private
def port
@server.port
end
def uri
"http://0.0.0.0:#{port}/solr/"
end
def up
while starting
puts "Sunspot server is starting..."
end
puts "Sunspot server took #{'%.2f' % (Time.now - @started)} sec. to get up and running. Let's cuke!"
end
def starting
begin
sleep(1)
request = Net::HTTP.get_response(URI.parse(uri))
false
rescue Errno::ECONNREFUSED
true
end
end
end
Now we can the alternative start method and remove the explicit sleep statement in our global before hook. features/support/env.rb:
1
2
3
4
5
CukeSunspot.new.start
at_exit do
Sunspot::Rails::Server.new.stop
end
And voila, if you run cucumber, you scenario’s should run successfully. On my machine:
1
2
3
Sunspot server is starting...
Sunspot server is starting...
Sunspot server took 3.74 sec. to get up and running. Let's cuke!