specjour 0.1.11 → 0.1.12
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/README.markdown +15 -6
- data/VERSION +1 -1
- data/bin/specjour +5 -3
- data/lib/specjour/connection.rb +24 -11
- data/lib/specjour/dispatcher.rb +3 -2
- data/lib/specjour/manager.rb +4 -4
- data/lib/specjour/printer.rb +1 -1
- data/lib/specjour/protocol.rb +0 -13
- data/lib/specjour/worker.rb +2 -4
- data/lib/specjour.rb +1 -1
- metadata +2 -2
data/README.markdown
CHANGED
@@ -1,8 +1,8 @@
|
|
1
1
|
# Specjour
|
2
2
|
_Distribute your spec suite amongst your LAN via Bonjour._
|
3
3
|
|
4
|
-
1.
|
5
|
-
2.
|
4
|
+
1. Spin up a manager on each machine that can run your specs.
|
5
|
+
2. Start a dispatcher in your project directory.
|
6
6
|
3. Say farewell to your long coffee breaks.
|
7
7
|
|
8
8
|
## Requirements
|
@@ -14,7 +14,7 @@ _Distribute your spec suite amongst your LAN via Bonjour._
|
|
14
14
|
gem install specjour
|
15
15
|
|
16
16
|
## Start a manager
|
17
|
-
Running `specjour` on the command-line will start a manager which advertises that it's ready to run
|
17
|
+
Running `specjour` on the command-line will start a manager which advertises that it's ready to run specs. By default, the manager will only use one worker to run yours specs. If you had 4 cores however, you could use `specjour --workers 4` to run 4 sets of specs at once.
|
18
18
|
|
19
19
|
$ specjour
|
20
20
|
|
@@ -23,8 +23,8 @@ Require specjour's rake tasks in your project's `Rakefile`.
|
|
23
23
|
|
24
24
|
require 'specjour/tasks/specjour'
|
25
25
|
|
26
|
-
## Distribute the
|
27
|
-
Run the rake task to distribute the
|
26
|
+
## Distribute the specs
|
27
|
+
Run the rake task to distribute the specs among the managers you started.
|
28
28
|
|
29
29
|
$ rake specjour
|
30
30
|
|
@@ -38,7 +38,16 @@ Each worker should run their specs in an isolated database. Modify the test data
|
|
38
38
|
test:
|
39
39
|
database: blog_test<%=ENV['TEST_ENV_NUMBER']%>
|
40
40
|
|
41
|
-
Each worker will attempt to clear its database tables before running any specs via `DELETE FROM <table_name>;`. Additionally, test databases will be created if they don't exist (i.e. blog_test8 for the 8th worker) and will
|
41
|
+
Each worker will attempt to clear its database tables before running any specs via `DELETE FROM <table_name>;`. Additionally, test databases will be created if they don't exist (i.e. `CREATE DATABASE blog_test8` for the 8th worker) and will load your schema when it has fallen behind.
|
42
|
+
|
43
|
+
## Only listen to supported projects
|
44
|
+
By default, a manager will listen to all projects trying to distribute specs over the network. Sometimes you'll only want a manager to respond to one specific spec suite. You can accomplish this with the `--projects` flags.
|
45
|
+
|
46
|
+
$ specjour --projects bizconf # only run specs for the bizconf project
|
47
|
+
|
48
|
+
You could also listen to multiple projects:
|
49
|
+
|
50
|
+
$ specjour --projects bizconf,workbeast # only run specs for the bizconf and workbeast projects
|
42
51
|
|
43
52
|
## Note on Patches/Pull Requests
|
44
53
|
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.1.
|
1
|
+
0.1.12
|
data/bin/specjour
CHANGED
@@ -7,7 +7,7 @@ options = {:worker_size => 1, :batch_size => 1}
|
|
7
7
|
optparse = OptionParser.new do |opts|
|
8
8
|
opts.banner = "Usage: specjour [options]"
|
9
9
|
|
10
|
-
opts.on('-w', '--workers
|
10
|
+
opts.on('-w', '--workers WORKERS', Numeric, "Number of WORKERS to spin up, defaults to #{options[:worker_size]}") do |n|
|
11
11
|
options[:worker_size] = n
|
12
12
|
end
|
13
13
|
|
@@ -15,8 +15,8 @@ optparse = OptionParser.new do |opts|
|
|
15
15
|
options[:batch_size] = n
|
16
16
|
end
|
17
17
|
|
18
|
-
opts.on('-
|
19
|
-
options[:
|
18
|
+
opts.on('-p', '--projects PROJECTS', Array, "Only run specs for these comma delimited project names, i.e. workbeast,taigan") do |project_names|
|
19
|
+
options[:registered_projects] = project_names
|
20
20
|
end
|
21
21
|
|
22
22
|
opts.on('--do-work OPTIONS', Array, 'INTERNAL USE ONLY') do |args|
|
@@ -36,6 +36,8 @@ end
|
|
36
36
|
|
37
37
|
optparse.parse!
|
38
38
|
|
39
|
+
abort(%(ERROR: I don't understand the following flags: "#{ARGV.join(', ')}")) if ARGV.any?
|
40
|
+
|
39
41
|
if options[:worker_args]
|
40
42
|
options[:worker_args] << options[:batch_size]
|
41
43
|
Specjour::Worker.new(*options[:worker_args]).run
|
data/lib/specjour/connection.rb
CHANGED
@@ -5,25 +5,36 @@ module Specjour
|
|
5
5
|
include Protocol
|
6
6
|
extend Forwardable
|
7
7
|
|
8
|
-
attr_reader :uri
|
8
|
+
attr_reader :uri
|
9
|
+
attr_writer :socket
|
9
10
|
attr_accessor :reconnection_attempts
|
10
11
|
|
11
|
-
def_delegators :
|
12
|
+
def_delegators :socket, :flush, :closed?, :close, :gets, :each
|
13
|
+
|
14
|
+
def self.wrap(established_connection)
|
15
|
+
host, port = established_connection.peeraddr.values_at(2,1)
|
16
|
+
connection = new URI::Generic.build(:host => host, :port => port)
|
17
|
+
connection.socket = established_connection
|
18
|
+
connection
|
19
|
+
end
|
12
20
|
|
13
21
|
def initialize(uri)
|
14
22
|
@uri = uri
|
15
23
|
@reconnection_attempts = 0
|
16
|
-
connect
|
17
24
|
end
|
18
25
|
|
19
26
|
def connect
|
20
|
-
@
|
27
|
+
@socket = TCPSocket.open(uri.host, uri.port)
|
21
28
|
rescue SystemCallError => error
|
22
29
|
Kernel.puts "Could not connect to #{uri.to_s}\n#{error.inspect}"
|
23
30
|
end
|
24
31
|
|
32
|
+
def socket
|
33
|
+
@socket ||= connect
|
34
|
+
end
|
35
|
+
|
25
36
|
def print(arg)
|
26
|
-
|
37
|
+
socket.print dump_object(arg)
|
27
38
|
rescue SystemCallError => error
|
28
39
|
Kernel.p error
|
29
40
|
reconnect
|
@@ -34,8 +45,15 @@ module Specjour
|
|
34
45
|
print(arg << "\n")
|
35
46
|
end
|
36
47
|
|
48
|
+
def send_message(method_name, *args)
|
49
|
+
print([method_name, *args])
|
50
|
+
flush
|
51
|
+
end
|
52
|
+
|
53
|
+
protected
|
54
|
+
|
37
55
|
def reconnect
|
38
|
-
|
56
|
+
socket.close
|
39
57
|
if reconnection_attempts < MAX_RECONNECTS
|
40
58
|
connect
|
41
59
|
self.reconnection_attempts += 1
|
@@ -43,10 +61,5 @@ module Specjour
|
|
43
61
|
raise Error, "Lost connection #{MAX_RECONNECTS} times"
|
44
62
|
end
|
45
63
|
end
|
46
|
-
|
47
|
-
def send_message(method_name, *args)
|
48
|
-
print([method_name, *args])
|
49
|
-
flush
|
50
|
-
end
|
51
64
|
end
|
52
65
|
end
|
data/lib/specjour/dispatcher.rb
CHANGED
@@ -24,7 +24,7 @@ module Specjour
|
|
24
24
|
|
25
25
|
def all_specs
|
26
26
|
@all_specs ||= Dir.chdir(project_path) do
|
27
|
-
Dir["spec/**/**/*_spec.rb"].
|
27
|
+
Dir["spec/**/**/*_spec.rb"].sort
|
28
28
|
end
|
29
29
|
end
|
30
30
|
|
@@ -41,7 +41,7 @@ module Specjour
|
|
41
41
|
|
42
42
|
def fetch_manager(uri)
|
43
43
|
manager = DRbObject.new_with_uri(uri.to_s)
|
44
|
-
if !managers.include?(manager) && manager.available_for?(
|
44
|
+
if !managers.include?(manager) && manager.available_for?(project_name)
|
45
45
|
set_up_manager(manager, uri)
|
46
46
|
managers << manager
|
47
47
|
self.worker_size += manager.worker_size
|
@@ -65,6 +65,7 @@ module Specjour
|
|
65
65
|
end
|
66
66
|
puts "Managers found: #{managers.size}"
|
67
67
|
abort unless managers.size > 0
|
68
|
+
puts "Workers found: #{worker_size}"
|
68
69
|
printer.worker_size = worker_size
|
69
70
|
end
|
70
71
|
|
data/lib/specjour/manager.rb
CHANGED
@@ -4,17 +4,17 @@ module Specjour
|
|
4
4
|
include DRbUndumped
|
5
5
|
|
6
6
|
attr_accessor :project_name, :specs_to_run, :dispatcher_uri
|
7
|
-
attr_reader :worker_size, :batch_size, :
|
7
|
+
attr_reader :worker_size, :batch_size, :registered_projects, :bonjour_service, :worker_pids
|
8
8
|
|
9
9
|
def initialize(options = {})
|
10
10
|
@worker_size = options[:worker_size]
|
11
11
|
@batch_size = options[:batch_size]
|
12
|
-
@
|
12
|
+
@registered_projects = options[:registered_projects]
|
13
13
|
@worker_pids = []
|
14
14
|
end
|
15
15
|
|
16
|
-
def available_for?(
|
17
|
-
|
16
|
+
def available_for?(project_name)
|
17
|
+
registered_projects ? registered_projects.include?(project_name) : true
|
18
18
|
end
|
19
19
|
|
20
20
|
def bundle_install
|
data/lib/specjour/printer.rb
CHANGED
data/lib/specjour/protocol.rb
CHANGED
@@ -10,18 +10,5 @@ module Specjour
|
|
10
10
|
def load_object(data)
|
11
11
|
Marshal.load(data.sub(TERMINATOR_REGEXP, ''))
|
12
12
|
end
|
13
|
-
|
14
|
-
def print(arg)
|
15
|
-
super dump_object(arg)
|
16
|
-
end
|
17
|
-
|
18
|
-
def puts(arg)
|
19
|
-
print(arg << "\n")
|
20
|
-
end
|
21
|
-
|
22
|
-
def send_message(method_name, *args)
|
23
|
-
print([method_name, *args])
|
24
|
-
flush
|
25
|
-
end
|
26
13
|
end
|
27
14
|
end
|
data/lib/specjour/worker.rb
CHANGED
@@ -10,10 +10,8 @@ module Specjour
|
|
10
10
|
@number = number.to_i
|
11
11
|
@batch_size = batch_size.to_i
|
12
12
|
self.printer_uri = printer_uri
|
13
|
-
printer
|
14
13
|
GC.copy_on_write_friendly = true if GC.respond_to?(:copy_on_write_friendly=)
|
15
14
|
DistributedFormatter.batch_size = batch_size
|
16
|
-
Dir.chdir(project_path)
|
17
15
|
set_env_variables
|
18
16
|
end
|
19
17
|
|
@@ -24,6 +22,7 @@ module Specjour
|
|
24
22
|
def run
|
25
23
|
printer.send_message(:ready)
|
26
24
|
run_time = 0
|
25
|
+
Dir.chdir(project_path)
|
27
26
|
while !printer.closed? && data = printer.gets(TERMINATOR)
|
28
27
|
spec = load_object(data)
|
29
28
|
if spec
|
@@ -50,7 +49,7 @@ module Specjour
|
|
50
49
|
end
|
51
50
|
|
52
51
|
def run_spec(spec)
|
53
|
-
|
52
|
+
puts "Running #{spec}"
|
54
53
|
options = Spec::Runner::OptionParser.parse(
|
55
54
|
['--format=Specjour::DistributedFormatter', spec],
|
56
55
|
$stderr,
|
@@ -58,7 +57,6 @@ module Specjour
|
|
58
57
|
)
|
59
58
|
Spec::Runner.use options
|
60
59
|
options.run_examples
|
61
|
-
Spec::Runner.options.instance_variable_set(:@examples_run, true)
|
62
60
|
end
|
63
61
|
|
64
62
|
def set_env_variables
|
data/lib/specjour.rb
CHANGED