specjour 0.1.18 → 0.2.0
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/History.markdown +8 -0
- data/README.markdown +5 -0
- data/VERSION +1 -1
- data/bin/specjour +3 -2
- data/lib/specjour/connection.rb +8 -2
- data/lib/specjour/cpu.rb +13 -0
- data/lib/specjour/cucumber/dispatcher.rb +18 -0
- data/lib/specjour/cucumber/distributed_formatter.rb +55 -0
- data/lib/specjour/cucumber/final_report.rb +73 -0
- data/lib/specjour/cucumber/printer.rb +9 -0
- data/lib/specjour/cucumber.rb +14 -0
- data/lib/specjour/dispatcher.rb +2 -6
- data/lib/specjour/manager.rb +1 -0
- data/lib/specjour/printer.rb +16 -4
- data/lib/specjour/{distributed_formatter.rb → rspec/distributed_formatter.rb} +2 -2
- data/lib/specjour/rspec/final_report.rb +62 -0
- data/lib/specjour/{marshalable_failure_formatter.rb → rspec/marshalable_failure_formatter.rb} +1 -1
- data/lib/specjour/{marshalable_rspec_failure.rb → rspec/marshalable_rspec_failure.rb} +1 -1
- data/lib/specjour/rspec.rb +10 -0
- data/lib/specjour/rsync_daemon.rb +1 -1
- data/lib/specjour/tasks/dispatch.rake +10 -0
- data/lib/specjour/worker.rb +33 -10
- data/lib/specjour.rb +7 -9
- metadata +16 -12
- data/lib/specjour/core_ext/array.rb +0 -15
- data/lib/specjour/final_report.rb +0 -60
- data/spec/lib/specjour/connection_spec.rb +0 -21
- data/spec/lib/specjour/core_ext/array_spec.rb +0 -31
data/History.markdown
ADDED
data/README.markdown
CHANGED
@@ -31,6 +31,11 @@ Run the rake task to distribute the specs among the managers you started.
|
|
31
31
|
|
32
32
|
$ rake specjour
|
33
33
|
|
34
|
+
## Distribute the features
|
35
|
+
Run the rake task to distribute the features among the managers you started.
|
36
|
+
|
37
|
+
$ rake specjour:cucumber
|
38
|
+
|
34
39
|
## Rails
|
35
40
|
Edit your config/environment.rb
|
36
41
|
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.
|
1
|
+
0.2.0
|
data/bin/specjour
CHANGED
@@ -2,12 +2,12 @@
|
|
2
2
|
require 'optparse'
|
3
3
|
require 'specjour'
|
4
4
|
|
5
|
-
options = {:
|
5
|
+
options = {:batch_size => 1}
|
6
6
|
|
7
7
|
optparse = OptionParser.new do |opts|
|
8
8
|
opts.banner = "Usage: specjour [options]"
|
9
9
|
|
10
|
-
opts.on('-w', '--workers WORKERS', Numeric, "Number of WORKERS to spin up, defaults to
|
10
|
+
opts.on('-w', '--workers WORKERS', Numeric, "Number of WORKERS to spin up, defaults to available cores") do |n|
|
11
11
|
options[:worker_size] = n
|
12
12
|
end
|
13
13
|
|
@@ -46,5 +46,6 @@ if options[:worker_args]
|
|
46
46
|
options[:worker_args] << options[:batch_size]
|
47
47
|
Specjour::Worker.new(*options[:worker_args]).run
|
48
48
|
else
|
49
|
+
options[:worker_size] ||= Specjour::CPU.cores
|
49
50
|
Specjour::Manager.new(options).start
|
50
51
|
end
|
data/lib/specjour/connection.rb
CHANGED
@@ -6,7 +6,7 @@ module Specjour
|
|
6
6
|
attr_reader :uri
|
7
7
|
attr_writer :socket
|
8
8
|
|
9
|
-
def_delegators :socket, :flush, :closed?, :
|
9
|
+
def_delegators :socket, :flush, :closed?, :gets, :each
|
10
10
|
|
11
11
|
def self.wrap(established_connection)
|
12
12
|
host, port = established_connection.peeraddr.values_at(3,1)
|
@@ -19,16 +19,22 @@ module Specjour
|
|
19
19
|
@uri = uri
|
20
20
|
end
|
21
21
|
|
22
|
+
alias to_str to_s
|
23
|
+
|
22
24
|
def connect
|
23
25
|
timeout { connect_socket }
|
24
26
|
end
|
25
27
|
|
28
|
+
def disconnect
|
29
|
+
socket.close
|
30
|
+
end
|
31
|
+
|
26
32
|
def socket
|
27
33
|
@socket ||= connect
|
28
34
|
end
|
29
35
|
|
30
36
|
def timeout(&block)
|
31
|
-
Timeout.timeout(
|
37
|
+
Timeout.timeout(2, &block)
|
32
38
|
rescue Timeout::Error
|
33
39
|
raise Error, "Connection to dispatcher timed out"
|
34
40
|
end
|
data/lib/specjour/cpu.rb
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
module Specjour
|
2
|
+
module Cucumber
|
3
|
+
class Dispatcher < ::Specjour::Dispatcher
|
4
|
+
|
5
|
+
protected
|
6
|
+
|
7
|
+
def all_specs
|
8
|
+
@all_specs ||= Dir.chdir(project_path) do
|
9
|
+
Dir["features/**/*.feature"]
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
def printer
|
14
|
+
@printer ||= Printer.start(all_specs)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,55 @@
|
|
1
|
+
module Specjour::Cucumber
|
2
|
+
class DistributedFormatter < ::Cucumber::Formatter::Progress
|
3
|
+
class << self
|
4
|
+
attr_accessor :batch_size
|
5
|
+
end
|
6
|
+
@batch_size = 1
|
7
|
+
|
8
|
+
def initialize(step_mother, io, options)
|
9
|
+
@step_mother = step_mother
|
10
|
+
@io = io
|
11
|
+
@options = options
|
12
|
+
@failing_scenarios = []
|
13
|
+
end
|
14
|
+
|
15
|
+
def after_features(features)
|
16
|
+
print_summary
|
17
|
+
step_mother.scenarios.clear
|
18
|
+
step_mother.steps.clear
|
19
|
+
end
|
20
|
+
|
21
|
+
def prepare_failures
|
22
|
+
@failures = step_mother.scenarios(:failed).select { |s| s.is_a?(Cucumber::Ast::Scenario) }
|
23
|
+
|
24
|
+
if !@failures.empty?
|
25
|
+
@failures.each do |failure|
|
26
|
+
failure_message = ''
|
27
|
+
failure_message += format_string("cucumber " + failure.file_colon_line, :failed) +
|
28
|
+
failure_message += format_string(" # Scenario: " + failure.name, :comment)
|
29
|
+
@failing_scenarios << failure_message
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
def print_summary
|
35
|
+
prepare_failures
|
36
|
+
|
37
|
+
@io.send_message(:worker_summary=, to_hash)
|
38
|
+
end
|
39
|
+
|
40
|
+
OUTCOMES = [:failed, :skipped, :undefined, :pending, :passed]
|
41
|
+
|
42
|
+
def to_hash
|
43
|
+
hash = {}
|
44
|
+
[:scenarios, :steps].each do |type|
|
45
|
+
hash[type] = {}
|
46
|
+
OUTCOMES.each do |outcome|
|
47
|
+
hash[type][outcome] = step_mother.send(type, outcome).size
|
48
|
+
end
|
49
|
+
end
|
50
|
+
hash.merge!(:failing_scenarios => @failing_scenarios)
|
51
|
+
hash
|
52
|
+
end
|
53
|
+
|
54
|
+
end
|
55
|
+
end
|
@@ -0,0 +1,73 @@
|
|
1
|
+
module Specjour
|
2
|
+
module Cucumber
|
3
|
+
class Summarizer
|
4
|
+
attr_reader :duration, :failing_scenarios
|
5
|
+
def initialize
|
6
|
+
@duration = 0.0
|
7
|
+
@failing_scenarios = []
|
8
|
+
@scenarios = Hash.new(0)
|
9
|
+
@steps = Hash.new(0)
|
10
|
+
end
|
11
|
+
|
12
|
+
def increment(category, type, count)
|
13
|
+
current = instance_variable_get("@#{category}")
|
14
|
+
current[type] += count
|
15
|
+
end
|
16
|
+
|
17
|
+
def add(stats)
|
18
|
+
stats.each do |category, hash|
|
19
|
+
if category == :failing_scenarios
|
20
|
+
@failing_scenarios += hash
|
21
|
+
elsif category == :duration
|
22
|
+
@duration = hash.to_f if duration < hash.to_f
|
23
|
+
else
|
24
|
+
hash.each do |type, count|
|
25
|
+
increment(category, type, count)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
def scenarios(status=nil)
|
32
|
+
require 'ostruct'
|
33
|
+
length = status ? @scenarios[status] : @scenarios.inject(0) {|h,(k,v)| h += v}
|
34
|
+
any = @scenarios[status] > 0 if status
|
35
|
+
OpenStruct.new(:length => length , :any? => any)
|
36
|
+
end
|
37
|
+
|
38
|
+
def steps(status=nil)
|
39
|
+
require 'ostruct'
|
40
|
+
length = status ? @steps[status] : @steps.inject(0) {|h,(k,v)| h += v}
|
41
|
+
any = @steps[status] > 0 if status
|
42
|
+
OpenStruct.new(:length => length , :any? => any)
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
class FinalReport
|
47
|
+
include ::Cucumber::Formatter::Console
|
48
|
+
def initialize
|
49
|
+
@features = []
|
50
|
+
@summarizer = Summarizer.new
|
51
|
+
end
|
52
|
+
|
53
|
+
def add(stats)
|
54
|
+
@summarizer.add(stats)
|
55
|
+
end
|
56
|
+
|
57
|
+
def summarize
|
58
|
+
if @summarizer.failing_scenarios.any?
|
59
|
+
puts
|
60
|
+
puts
|
61
|
+
puts format_string("Failing Scenarios:", :failed)
|
62
|
+
@summarizer.failing_scenarios.each {|f| puts f }
|
63
|
+
end
|
64
|
+
|
65
|
+
default_format = lambda {|status_count, status| format_string(status_count, status)}
|
66
|
+
puts
|
67
|
+
puts scenario_summary(@summarizer, &default_format)
|
68
|
+
puts step_summary(@summarizer, &default_format)
|
69
|
+
puts format_duration(@summarizer.duration) if @summarizer.duration
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
module Specjour
|
2
|
+
module Cucumber
|
3
|
+
begin
|
4
|
+
require 'cucumber'
|
5
|
+
require 'cucumber/formatter/progress'
|
6
|
+
|
7
|
+
require 'specjour/cucumber/dispatcher'
|
8
|
+
require 'specjour/cucumber/distributed_formatter'
|
9
|
+
require 'specjour/cucumber/final_report'
|
10
|
+
require 'specjour/cucumber/printer'
|
11
|
+
rescue LoadError
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
data/lib/specjour/dispatcher.rb
CHANGED
@@ -41,7 +41,7 @@ module Specjour
|
|
41
41
|
end
|
42
42
|
|
43
43
|
def fetch_manager(uri)
|
44
|
-
Timeout.timeout(
|
44
|
+
Timeout.timeout(8) do
|
45
45
|
manager = DRbObject.new_with_uri(uri.to_s)
|
46
46
|
if !managers.include?(manager) && manager.available_for?(project_name)
|
47
47
|
set_up_manager(manager, uri)
|
@@ -75,11 +75,7 @@ module Specjour
|
|
75
75
|
end
|
76
76
|
|
77
77
|
def printer
|
78
|
-
@printer ||=
|
79
|
-
p = Printer.new
|
80
|
-
p.specs_to_run = all_specs
|
81
|
-
p.start
|
82
|
-
end
|
78
|
+
@printer ||= Printer.start(all_specs)
|
83
79
|
end
|
84
80
|
|
85
81
|
def project_name
|
data/lib/specjour/manager.rb
CHANGED
@@ -48,6 +48,7 @@ module Specjour
|
|
48
48
|
end
|
49
49
|
|
50
50
|
def dispatch_workers
|
51
|
+
GC.copy_on_write_friendly = true if GC.respond_to?(:copy_on_write_friendly=)
|
51
52
|
(1..worker_size).each do |index|
|
52
53
|
worker_pids << fork do
|
53
54
|
exec("specjour --batch-size #{batch_size} #{'--log' if Specjour.log?} --do-work #{project_path},#{dispatcher_uri},#{index}")
|
data/lib/specjour/printer.rb
CHANGED
@@ -3,9 +3,13 @@ module Specjour
|
|
3
3
|
include Protocol
|
4
4
|
RANDOM_PORT = 0
|
5
5
|
|
6
|
-
|
6
|
+
def self.start(specs_to_run)
|
7
|
+
new(specs_to_run).start
|
8
|
+
end
|
9
|
+
|
10
|
+
attr_accessor :worker_size, :specs_to_run, :completed_workers, :disconnections
|
7
11
|
|
8
|
-
def initialize
|
12
|
+
def initialize(specs_to_run)
|
9
13
|
super(
|
10
14
|
port = RANDOM_PORT,
|
11
15
|
host = "0.0.0.0",
|
@@ -15,6 +19,8 @@ module Specjour
|
|
15
19
|
debug = true
|
16
20
|
)
|
17
21
|
@completed_workers = 0
|
22
|
+
@disconnections = 0
|
23
|
+
self.specs_to_run = specs_to_run
|
18
24
|
end
|
19
25
|
|
20
26
|
def serve(client)
|
@@ -40,7 +46,8 @@ module Specjour
|
|
40
46
|
protected
|
41
47
|
|
42
48
|
def disconnecting(client_port)
|
43
|
-
|
49
|
+
self.disconnections += 1
|
50
|
+
if disconnections == worker_size
|
44
51
|
stop
|
45
52
|
end
|
46
53
|
end
|
@@ -59,11 +66,16 @@ module Specjour
|
|
59
66
|
end
|
60
67
|
|
61
68
|
def report
|
62
|
-
@report ||= FinalReport.new
|
69
|
+
@report ||= Rspec::FinalReport.new
|
63
70
|
end
|
64
71
|
|
65
72
|
def stopping
|
66
73
|
report.summarize
|
74
|
+
if disconnections != completed_workers
|
75
|
+
puts "*" * 63
|
76
|
+
puts "* ERROR: NOT ALL WORKERS COMPLETED PROPERLY, RE-RUN THE SUITE *"
|
77
|
+
puts "*" * 63
|
78
|
+
end
|
67
79
|
end
|
68
80
|
end
|
69
81
|
end
|
@@ -0,0 +1,62 @@
|
|
1
|
+
module Specjour
|
2
|
+
module Rspec
|
3
|
+
class FinalReport
|
4
|
+
require 'specjour/rspec/marshalable_rspec_failure'
|
5
|
+
attr_reader :duration, :example_count, :failure_count, :pending_count, :pending_examples, :failing_examples
|
6
|
+
|
7
|
+
def initialize
|
8
|
+
@duration = 0.0
|
9
|
+
@example_count = 0
|
10
|
+
@failure_count = 0
|
11
|
+
@pending_count = 0
|
12
|
+
@pending_examples = []
|
13
|
+
@failing_examples = []
|
14
|
+
end
|
15
|
+
|
16
|
+
def add(stats)
|
17
|
+
stats.each do |key, value|
|
18
|
+
if key == :duration
|
19
|
+
@duration = value.to_f if duration < value.to_f
|
20
|
+
else
|
21
|
+
increment(key, value)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
def increment(key, value)
|
27
|
+
current = instance_variable_get("@#{key}")
|
28
|
+
instance_variable_set("@#{key}", current + value)
|
29
|
+
end
|
30
|
+
|
31
|
+
def formatter_options
|
32
|
+
@formatter_options ||= OpenStruct.new(
|
33
|
+
:colour => true,
|
34
|
+
:autospec => false,
|
35
|
+
:dry_run => false
|
36
|
+
)
|
37
|
+
end
|
38
|
+
|
39
|
+
def formatter
|
40
|
+
@formatter ||= begin
|
41
|
+
f = MarshalableFailureFormatter.new(formatter_options, $stdout)
|
42
|
+
f.instance_variable_set(:@pending_examples, pending_examples)
|
43
|
+
f
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
def summarize
|
48
|
+
if example_count > 0
|
49
|
+
formatter.dump_pending
|
50
|
+
dump_failures
|
51
|
+
formatter.dump_summary(duration, example_count, failure_count, pending_count)
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
def dump_failures
|
56
|
+
failing_examples.each_with_index do |failure, index|
|
57
|
+
formatter.dump_failure index + 1, failure
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
@@ -0,0 +1,10 @@
|
|
1
|
+
module Specjour
|
2
|
+
module Rspec
|
3
|
+
require 'spec'
|
4
|
+
require 'spec/runner/formatter/base_text_formatter'
|
5
|
+
|
6
|
+
autoload :DistributedFormatter, 'specjour/rspec/distributed_formatter'
|
7
|
+
autoload :FinalReport, 'specjour/rspec/final_report'
|
8
|
+
autoload :MarshalableFailureFormatter, 'specjour/rspec/marshalable_failure_formatter'
|
9
|
+
end
|
10
|
+
end
|
@@ -5,6 +5,16 @@ namespace :specjour do
|
|
5
5
|
args.with_defaults :project_path => Rake.original_dir
|
6
6
|
Specjour::Dispatcher.new(args.project_path).start
|
7
7
|
end
|
8
|
+
|
9
|
+
namespace :cucumber do
|
10
|
+
task :dispatch, [:project_path] do |task, args|
|
11
|
+
args.with_defaults :project_path => Rake.original_dir
|
12
|
+
Specjour::Cucumber::Dispatcher.new(args.project_path).start
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
desc "Dispatch the project to listening managers"
|
17
|
+
task :cucumber => "cucumber:dispatch"
|
8
18
|
end
|
9
19
|
|
10
20
|
desc "Dispatch the project to listening managers"
|
data/lib/specjour/worker.rb
CHANGED
@@ -1,4 +1,6 @@
|
|
1
1
|
module Specjour
|
2
|
+
require 'specjour/cucumber'
|
3
|
+
|
2
4
|
class Worker
|
3
5
|
include Protocol
|
4
6
|
include SocketHelpers
|
@@ -11,8 +13,7 @@ module Specjour
|
|
11
13
|
@number = number.to_i
|
12
14
|
@batch_size = batch_size.to_i
|
13
15
|
self.printer_uri = printer_uri
|
14
|
-
|
15
|
-
DistributedFormatter.batch_size = batch_size
|
16
|
+
Rspec::DistributedFormatter.batch_size = batch_size
|
16
17
|
set_env_variables
|
17
18
|
end
|
18
19
|
|
@@ -25,16 +26,16 @@ module Specjour
|
|
25
26
|
run_time = 0
|
26
27
|
Dir.chdir(project_path)
|
27
28
|
while !printer.closed? && data = printer.gets(TERMINATOR)
|
28
|
-
|
29
|
-
if
|
29
|
+
test = load_object(data)
|
30
|
+
if test
|
30
31
|
run_time += Benchmark.realtime do
|
31
|
-
|
32
|
+
run_test test
|
32
33
|
end
|
33
34
|
printer.send_message(:ready)
|
34
35
|
else
|
35
|
-
printer.send_message(:done)
|
36
36
|
printer.send_message(:worker_summary=, {:duration => sprintf("%6f", run_time)})
|
37
|
-
printer.
|
37
|
+
printer.send_message(:done)
|
38
|
+
printer.disconnect
|
38
39
|
end
|
39
40
|
end
|
40
41
|
end
|
@@ -49,12 +50,26 @@ module Specjour
|
|
49
50
|
Connection.new printer_uri
|
50
51
|
end
|
51
52
|
|
53
|
+
def run_test(test)
|
54
|
+
puts "Running #{test}"
|
55
|
+
if test =~ /\.feature$/
|
56
|
+
run_feature test
|
57
|
+
else
|
58
|
+
run_spec test
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
def run_feature(feature)
|
63
|
+
set_up_cucumber
|
64
|
+
cli = ::Cucumber::Cli::Main.new(['--format', 'Specjour::Cucumber::DistributedFormatter', feature], printer)
|
65
|
+
cli.execute!(::Cucumber::Cli::Main.step_mother)
|
66
|
+
end
|
67
|
+
|
52
68
|
def run_spec(spec)
|
53
|
-
puts "Running #{spec}"
|
54
69
|
options = Spec::Runner::OptionParser.parse(
|
55
|
-
['--format=Specjour::DistributedFormatter', spec],
|
70
|
+
['--format=Specjour::Rspec::DistributedFormatter', spec],
|
56
71
|
$stderr,
|
57
|
-
|
72
|
+
printer
|
58
73
|
)
|
59
74
|
Spec::Runner.use options
|
60
75
|
options.run_examples
|
@@ -65,5 +80,13 @@ module Specjour
|
|
65
80
|
ENV['RSPEC_COLOR'] = 'true'
|
66
81
|
ENV['TEST_ENV_NUMBER'] = number.to_s
|
67
82
|
end
|
83
|
+
|
84
|
+
def set_up_cucumber
|
85
|
+
unless @cucumber_loaded
|
86
|
+
Cucumber::DistributedFormatter.batch_size = batch_size
|
87
|
+
::Cucumber::Cli::Options.class_eval { def print_profile_information; end }
|
88
|
+
@cucumber_loaded = true
|
89
|
+
end
|
90
|
+
end
|
68
91
|
end
|
69
92
|
end
|
data/lib/specjour.rb
CHANGED
@@ -1,10 +1,6 @@
|
|
1
|
-
require '
|
2
|
-
require 'spec/runner/formatter/base_text_formatter'
|
3
|
-
require 'specjour/protocol'
|
4
|
-
require 'specjour/core_ext/array'
|
1
|
+
require 'drb'
|
5
2
|
|
6
3
|
autoload :URI, 'uri'
|
7
|
-
autoload :DRb, 'drb'
|
8
4
|
autoload :Forwardable, 'forwardable'
|
9
5
|
autoload :GServer, 'gserver'
|
10
6
|
autoload :Timeout, 'timeout'
|
@@ -13,18 +9,20 @@ autoload :Logger, 'logger'
|
|
13
9
|
autoload :Socket, 'socket'
|
14
10
|
|
15
11
|
module Specjour
|
12
|
+
autoload :CPU, 'specjour/cpu'
|
16
13
|
autoload :Connection, 'specjour/connection'
|
17
14
|
autoload :Dispatcher, 'specjour/dispatcher'
|
18
|
-
autoload :DistributedFormatter, 'specjour/distributed_formatter'
|
19
|
-
autoload :FinalReport, 'specjour/final_report'
|
20
15
|
autoload :Manager, 'specjour/manager'
|
21
|
-
autoload :MarshalableFailureFormatter, 'specjour/marshalable_failure_formatter'
|
22
16
|
autoload :Printer, 'specjour/printer'
|
17
|
+
autoload :Protocol, 'specjour/protocol'
|
23
18
|
autoload :RsyncDaemon, 'specjour/rsync_daemon'
|
24
19
|
autoload :SocketHelpers, 'specjour/socket_helpers'
|
25
20
|
autoload :Worker, 'specjour/worker'
|
26
21
|
|
27
|
-
|
22
|
+
autoload :Cucumber, 'specjour/cucumber'
|
23
|
+
autoload :Rspec, 'specjour/rspec'
|
24
|
+
|
25
|
+
VERSION = "0.2.0".freeze
|
28
26
|
|
29
27
|
class Error < StandardError; end
|
30
28
|
|
metadata
CHANGED
@@ -4,9 +4,9 @@ version: !ruby/object:Gem::Version
|
|
4
4
|
prerelease: false
|
5
5
|
segments:
|
6
6
|
- 0
|
7
|
-
-
|
8
|
-
-
|
9
|
-
version: 0.
|
7
|
+
- 2
|
8
|
+
- 0
|
9
|
+
version: 0.2.0
|
10
10
|
platform: ruby
|
11
11
|
authors:
|
12
12
|
- Sandro Turriate
|
@@ -14,7 +14,7 @@ autorequire:
|
|
14
14
|
bindir: bin
|
15
15
|
cert_chain: []
|
16
16
|
|
17
|
-
date: 2010-04-
|
17
|
+
date: 2010-04-20 00:00:00 -04:00
|
18
18
|
default_executable: specjour
|
19
19
|
dependencies:
|
20
20
|
- !ruby/object:Gem::Dependency
|
@@ -82,6 +82,7 @@ extra_rdoc_files:
|
|
82
82
|
files:
|
83
83
|
- .document
|
84
84
|
- .gitignore
|
85
|
+
- History.markdown
|
85
86
|
- MIT_LICENSE
|
86
87
|
- README.markdown
|
87
88
|
- Rakefile
|
@@ -89,23 +90,28 @@ files:
|
|
89
90
|
- bin/specjour
|
90
91
|
- lib/specjour.rb
|
91
92
|
- lib/specjour/connection.rb
|
92
|
-
- lib/specjour/
|
93
|
+
- lib/specjour/cpu.rb
|
94
|
+
- lib/specjour/cucumber.rb
|
95
|
+
- lib/specjour/cucumber/dispatcher.rb
|
96
|
+
- lib/specjour/cucumber/distributed_formatter.rb
|
97
|
+
- lib/specjour/cucumber/final_report.rb
|
98
|
+
- lib/specjour/cucumber/printer.rb
|
93
99
|
- lib/specjour/db_scrub.rb
|
94
100
|
- lib/specjour/dispatcher.rb
|
95
|
-
- lib/specjour/distributed_formatter.rb
|
96
|
-
- lib/specjour/final_report.rb
|
97
101
|
- lib/specjour/manager.rb
|
98
|
-
- lib/specjour/marshalable_failure_formatter.rb
|
99
|
-
- lib/specjour/marshalable_rspec_failure.rb
|
100
102
|
- lib/specjour/printer.rb
|
101
103
|
- lib/specjour/protocol.rb
|
104
|
+
- lib/specjour/rspec.rb
|
105
|
+
- lib/specjour/rspec/distributed_formatter.rb
|
106
|
+
- lib/specjour/rspec/final_report.rb
|
107
|
+
- lib/specjour/rspec/marshalable_failure_formatter.rb
|
108
|
+
- lib/specjour/rspec/marshalable_rspec_failure.rb
|
102
109
|
- lib/specjour/rsync_daemon.rb
|
103
110
|
- lib/specjour/socket_helpers.rb
|
104
111
|
- lib/specjour/tasks/dispatch.rake
|
105
112
|
- lib/specjour/tasks/specjour.rb
|
106
113
|
- lib/specjour/worker.rb
|
107
114
|
- rails/init.rb
|
108
|
-
- spec/lib/specjour/core_ext/array_spec.rb
|
109
115
|
- spec/lib/specjour/worker_spec.rb
|
110
116
|
- spec/spec.opts
|
111
117
|
- spec/spec_helper.rb
|
@@ -141,8 +147,6 @@ signing_key:
|
|
141
147
|
specification_version: 3
|
142
148
|
summary: Distribute your spec suite amongst your LAN via Bonjour.
|
143
149
|
test_files:
|
144
|
-
- spec/lib/specjour/connection_spec.rb
|
145
|
-
- spec/lib/specjour/core_ext/array_spec.rb
|
146
150
|
- spec/lib/specjour/worker_spec.rb
|
147
151
|
- spec/spec_helper.rb
|
148
152
|
- spec/specjour_spec.rb
|
@@ -1,15 +0,0 @@
|
|
1
|
-
module Specjour
|
2
|
-
module Among
|
3
|
-
def among(group_size)
|
4
|
-
group_size = 1 if group_size.zero?
|
5
|
-
groups = Array.new(group_size) { [] }
|
6
|
-
offset = 0
|
7
|
-
each do |item|
|
8
|
-
groups[offset] << item
|
9
|
-
offset = (offset == group_size - 1) ? 0 : offset + 1
|
10
|
-
end
|
11
|
-
groups
|
12
|
-
end
|
13
|
-
end
|
14
|
-
end
|
15
|
-
::Array.send(:include, Specjour::Among)
|
@@ -1,60 +0,0 @@
|
|
1
|
-
module Specjour
|
2
|
-
class FinalReport
|
3
|
-
require 'specjour/marshalable_rspec_failure'
|
4
|
-
attr_reader :duration, :example_count, :failure_count, :pending_count, :pending_examples, :failing_examples
|
5
|
-
|
6
|
-
def initialize
|
7
|
-
@duration = 0.0
|
8
|
-
@example_count = 0
|
9
|
-
@failure_count = 0
|
10
|
-
@pending_count = 0
|
11
|
-
@pending_examples = []
|
12
|
-
@failing_examples = []
|
13
|
-
end
|
14
|
-
|
15
|
-
def add(stats)
|
16
|
-
stats.each do |key, value|
|
17
|
-
if key == :duration
|
18
|
-
@duration = value.to_f if duration < value.to_f
|
19
|
-
else
|
20
|
-
increment(key, value)
|
21
|
-
end
|
22
|
-
end
|
23
|
-
end
|
24
|
-
|
25
|
-
def increment(key, value)
|
26
|
-
current = instance_variable_get("@#{key}")
|
27
|
-
instance_variable_set("@#{key}", current + value)
|
28
|
-
end
|
29
|
-
|
30
|
-
def formatter_options
|
31
|
-
@formatter_options ||= OpenStruct.new(
|
32
|
-
:colour => true,
|
33
|
-
:autospec => false,
|
34
|
-
:dry_run => false
|
35
|
-
)
|
36
|
-
end
|
37
|
-
|
38
|
-
def formatter
|
39
|
-
@formatter ||= begin
|
40
|
-
f = MarshalableFailureFormatter.new(formatter_options, $stdout)
|
41
|
-
f.instance_variable_set(:@pending_examples, pending_examples)
|
42
|
-
f
|
43
|
-
end
|
44
|
-
end
|
45
|
-
|
46
|
-
def summarize
|
47
|
-
if example_count > 0
|
48
|
-
formatter.dump_pending
|
49
|
-
dump_failures
|
50
|
-
formatter.dump_summary(duration, example_count, failure_count, pending_count)
|
51
|
-
end
|
52
|
-
end
|
53
|
-
|
54
|
-
def dump_failures
|
55
|
-
failing_examples.each_with_index do |failure, index|
|
56
|
-
formatter.dump_failure index + 1, failure
|
57
|
-
end
|
58
|
-
end
|
59
|
-
end
|
60
|
-
end
|
@@ -1,21 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
|
3
|
-
describe Specjour::Connection do
|
4
|
-
require 'stringio'
|
5
|
-
describe "#print" do
|
6
|
-
context "connection unavailable" do
|
7
|
-
let(:connection) do
|
8
|
-
Specjour::Connection.new(URI.parse("specjour://me.local:12345"))
|
9
|
-
end
|
10
|
-
|
11
|
-
it "reconnects" do
|
12
|
-
socket = mock(:closed? => false, :close => true)
|
13
|
-
socket.stub(:print).and_raise(Errno::EPIPE)
|
14
|
-
connection.instance_variable_set(:@socket, socket)
|
15
|
-
new_socket = mock(:print => true)
|
16
|
-
TCPSocket.stub(:open => new_socket)
|
17
|
-
connection.print('hi').should be_true
|
18
|
-
end
|
19
|
-
end
|
20
|
-
end
|
21
|
-
end
|
@@ -1,31 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
|
3
|
-
describe "Array splitting among many" do
|
4
|
-
describe "#among" do
|
5
|
-
let(:array) { [1,2,3,4,5] }
|
6
|
-
|
7
|
-
it "splits among 0" do
|
8
|
-
array.among(0).should == [[1,2,3,4,5]]
|
9
|
-
end
|
10
|
-
|
11
|
-
it "splits among by 1" do
|
12
|
-
array.among(1).should == [[1,2,3,4,5]]
|
13
|
-
end
|
14
|
-
|
15
|
-
it "splits among by 2" do
|
16
|
-
array.among(2).should == [[1,3,5],[2,4]]
|
17
|
-
end
|
18
|
-
|
19
|
-
it "splits among by 3" do
|
20
|
-
array.among(3).should == [[1,4],[2,5],[3]]
|
21
|
-
end
|
22
|
-
|
23
|
-
it "splits among by 4" do
|
24
|
-
array.among(4).should == [[1,5],[2],[3],[4]]
|
25
|
-
end
|
26
|
-
|
27
|
-
it "splits among by 5" do
|
28
|
-
array.among(5).should == [[1],[2],[3],[4],[5]]
|
29
|
-
end
|
30
|
-
end
|
31
|
-
end
|