minimal-buffet 0.6
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/bin/buffet +5 -0
- data/lib/buffet/cli.rb +29 -0
- data/lib/buffet/command_runner.rb +23 -0
- data/lib/buffet/master.rb +129 -0
- data/lib/buffet/project.rb +24 -0
- data/lib/buffet/runner.rb +93 -0
- data/lib/buffet/settings.rb +58 -0
- data/lib/buffet/slave.rb +48 -0
- data/lib/buffet/version.rb +3 -0
- data/lib/buffet.rb +60 -0
- data/support/buffet-worker +52 -0
- data/support/rspec1_formatter.rb +44 -0
- data/support/rspec2_formatter.rb +51 -0
- metadata +122 -0
data/bin/buffet
ADDED
data/lib/buffet/cli.rb
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
require 'buffet'
|
2
|
+
require 'optparse'
|
3
|
+
|
4
|
+
module Buffet
|
5
|
+
class CLI
|
6
|
+
def initialize args
|
7
|
+
opts = OptionParser.new do |opts|
|
8
|
+
opts.banner = "Usage: buffet [options] [spec-files]"
|
9
|
+
|
10
|
+
opts.on('-c', '--config CONFIG',
|
11
|
+
'Use the specified CONFIG file') do |config_file|
|
12
|
+
Settings.load_file File.expand_path(config_file)
|
13
|
+
end
|
14
|
+
|
15
|
+
opts.on('-p', '--project PROJECT',
|
16
|
+
'Use the specified PROJECT name') do |project_name|
|
17
|
+
Settings.project_name = project_name
|
18
|
+
end
|
19
|
+
end.parse!(args)
|
20
|
+
|
21
|
+
specs = Buffet.extract_specs_from(opts.empty? ? 'spec' : opts)
|
22
|
+
|
23
|
+
runner = Runner.new
|
24
|
+
runner.run specs
|
25
|
+
|
26
|
+
exit 1 if runner.failures?
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
require 'logger'
|
2
|
+
require 'wopen3'
|
3
|
+
|
4
|
+
module Buffet
|
5
|
+
class CommandRunner
|
6
|
+
def initialize logger = Logger.new(STDOUT)
|
7
|
+
@logger = logger
|
8
|
+
end
|
9
|
+
|
10
|
+
def run *command
|
11
|
+
start_time = Time.now
|
12
|
+
result = Wopen3.system *command
|
13
|
+
end_time = Time.now
|
14
|
+
@logger.info "\n" +
|
15
|
+
"command: #{command.join ' '}\n" +
|
16
|
+
"time: #{end_time - start_time}\n" +
|
17
|
+
"status: #{result.status}\n" +
|
18
|
+
"stdout:\n#{result.stdout}\n" +
|
19
|
+
"stderr:\n#{result.stderr}"
|
20
|
+
result
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,129 @@
|
|
1
|
+
require 'benchmark'
|
2
|
+
require 'drb'
|
3
|
+
require 'thread'
|
4
|
+
require 'socket'
|
5
|
+
|
6
|
+
module Buffet
|
7
|
+
class Master
|
8
|
+
attr_reader :failures, :stats
|
9
|
+
|
10
|
+
def initialize project, slaves, specs, listener
|
11
|
+
@project = project
|
12
|
+
@slaves = slaves
|
13
|
+
@stats = {:examples => 0, :failures => 0, :pending => 0}
|
14
|
+
@slaves_stats = Hash[@slaves.map do |slave|
|
15
|
+
[slave.user_at_host, stats.dup.merge!(:slave => slave)]
|
16
|
+
end]
|
17
|
+
@stats[:slaves] = @slaves_stats
|
18
|
+
@lock = Mutex.new
|
19
|
+
@failures = []
|
20
|
+
@specs = specs.shuffle # Never have the same test distribution
|
21
|
+
@listener = listener
|
22
|
+
end
|
23
|
+
|
24
|
+
def run
|
25
|
+
start_service
|
26
|
+
|
27
|
+
@stats[:total_time] = Benchmark.measure do
|
28
|
+
threads = @slaves.map do |slave|
|
29
|
+
Thread.new do
|
30
|
+
time = Benchmark.measure do
|
31
|
+
prepare_slave slave
|
32
|
+
run_slave slave
|
33
|
+
end.real
|
34
|
+
@lock.synchronize { @slaves_stats[slave.name][:total_time] = time }
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
threads.each { |t| t.join }
|
39
|
+
end.real
|
40
|
+
|
41
|
+
stop_service
|
42
|
+
end
|
43
|
+
|
44
|
+
def next_file_for slave_name
|
45
|
+
file = @lock.synchronize { @specs.shift }
|
46
|
+
if file
|
47
|
+
slave = @slaves_stats[slave_name][:slave]
|
48
|
+
@listener.spec_taken slave, file if file
|
49
|
+
end
|
50
|
+
file
|
51
|
+
end
|
52
|
+
|
53
|
+
def example_passed slave_name, details
|
54
|
+
@lock.synchronize do
|
55
|
+
@stats[:examples] += 1
|
56
|
+
@slaves_stats[slave_name][:examples] += 1
|
57
|
+
end
|
58
|
+
|
59
|
+
@listener.example_passed
|
60
|
+
end
|
61
|
+
|
62
|
+
def example_failed slave_name, details
|
63
|
+
@lock.synchronize do
|
64
|
+
@stats[:examples] += 1
|
65
|
+
@stats[:failures] += 1
|
66
|
+
@slaves_stats[slave_name][:failures] += 1
|
67
|
+
@failures << details
|
68
|
+
end
|
69
|
+
|
70
|
+
@listener.example_failed
|
71
|
+
end
|
72
|
+
|
73
|
+
def example_pending slave_name, details
|
74
|
+
@lock.synchronize do
|
75
|
+
@stats[:examples] += 1
|
76
|
+
@stats[:pending] += 1
|
77
|
+
@slaves_stats[slave_name][:pending] += 1
|
78
|
+
end
|
79
|
+
|
80
|
+
@listener.example_pending
|
81
|
+
end
|
82
|
+
|
83
|
+
private
|
84
|
+
|
85
|
+
def server_uri
|
86
|
+
@drb_server.uri
|
87
|
+
end
|
88
|
+
|
89
|
+
def start_service
|
90
|
+
@drb_server = DRb.start_service("druby://#{ip}:0", self)
|
91
|
+
end
|
92
|
+
|
93
|
+
def stop_service
|
94
|
+
DRb.stop_service
|
95
|
+
end
|
96
|
+
|
97
|
+
def ip
|
98
|
+
result = Buffet.run! 'host `hostname -s`'
|
99
|
+
result.stdout.chomp.match(/((\d+\.){3}\d+)/)[1]
|
100
|
+
end
|
101
|
+
|
102
|
+
def prepare_slave slave
|
103
|
+
time = Benchmark.measure do
|
104
|
+
@project.sync_to slave
|
105
|
+
|
106
|
+
if Settings.has_prepare_script?
|
107
|
+
slave.execute_in_project "#{Settings.prepare_script} #{Buffet.user} #{@project.name}"
|
108
|
+
end
|
109
|
+
|
110
|
+
# Copy support files so they can be run on the remote machine
|
111
|
+
slave.scp File.dirname(__FILE__) + '/../../support',
|
112
|
+
@project.support_dir_on_slave, :recurse => true
|
113
|
+
end.real
|
114
|
+
@lock.synchronize { @slaves_stats[slave.name][:prepare_time] = time }
|
115
|
+
|
116
|
+
@listener.slave_prepared slave
|
117
|
+
end
|
118
|
+
|
119
|
+
def run_slave slave
|
120
|
+
time = Benchmark.measure do
|
121
|
+
slave.execute_in_project(
|
122
|
+
".buffet/buffet-worker #{server_uri} #{slave.user_at_host} #{Settings.framework}")
|
123
|
+
end.real
|
124
|
+
@lock.synchronize { @slaves_stats[slave.name][:test_time] = time }
|
125
|
+
|
126
|
+
@listener.slave_finished slave
|
127
|
+
end
|
128
|
+
end
|
129
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
module Buffet
|
2
|
+
class Project
|
3
|
+
attr_accessor :name
|
4
|
+
attr_reader :directory
|
5
|
+
|
6
|
+
def initialize directory
|
7
|
+
@name = File.basename directory
|
8
|
+
@directory = File.expand_path directory
|
9
|
+
end
|
10
|
+
|
11
|
+
def directory_on_slave
|
12
|
+
"#{Buffet.workspace_dir}/#{name}"
|
13
|
+
end
|
14
|
+
|
15
|
+
def support_dir_on_slave
|
16
|
+
"#{directory_on_slave}/.buffet"
|
17
|
+
end
|
18
|
+
|
19
|
+
def sync_to slave
|
20
|
+
slave.execute "mkdir -p #{directory_on_slave}"
|
21
|
+
slave.rsync directory + '/', directory_on_slave
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,93 @@
|
|
1
|
+
require 'buffet'
|
2
|
+
require 'colorize'
|
3
|
+
|
4
|
+
module Buffet
|
5
|
+
class Runner
|
6
|
+
def initialize
|
7
|
+
@project = Settings.project
|
8
|
+
end
|
9
|
+
|
10
|
+
def run specs = nil
|
11
|
+
@specs = specs
|
12
|
+
raise 'No specs found' if @specs.empty?
|
13
|
+
|
14
|
+
@slaves = Settings.slaves
|
15
|
+
raise 'No slaves defined in settings.yml' if @slaves.empty?
|
16
|
+
|
17
|
+
Buffet.logger.info "Starting Buffet test run"
|
18
|
+
puts "Running Buffet..."
|
19
|
+
|
20
|
+
run_tests
|
21
|
+
display_results
|
22
|
+
end
|
23
|
+
|
24
|
+
def slave_prepared slave
|
25
|
+
Buffet.logger.info "#{slave.name} prepared"
|
26
|
+
end
|
27
|
+
|
28
|
+
def spec_taken slave, spec_file
|
29
|
+
Buffet.logger.info "#{slave.name} took #{spec_file}"
|
30
|
+
end
|
31
|
+
|
32
|
+
def example_passed
|
33
|
+
print '.'.green
|
34
|
+
STDOUT.flush
|
35
|
+
end
|
36
|
+
|
37
|
+
def example_failed
|
38
|
+
print 'F'.red
|
39
|
+
STDOUT.flush
|
40
|
+
end
|
41
|
+
|
42
|
+
def example_pending
|
43
|
+
print '*'.yellow
|
44
|
+
STDOUT.flush
|
45
|
+
end
|
46
|
+
|
47
|
+
def slave_finished slave
|
48
|
+
Buffet.logger.info "#{slave.name} finished"
|
49
|
+
end
|
50
|
+
|
51
|
+
def failures?
|
52
|
+
@master.failures.any?
|
53
|
+
end
|
54
|
+
|
55
|
+
private
|
56
|
+
|
57
|
+
def run_tests
|
58
|
+
@master = Master.new @project, @slaves, @specs, self
|
59
|
+
@master.run
|
60
|
+
end
|
61
|
+
|
62
|
+
def display_results
|
63
|
+
results = []
|
64
|
+
results << "\n"
|
65
|
+
|
66
|
+
@master.stats[:slaves].each do |slave_name, slave_stats|
|
67
|
+
results << "#{slave_name}:"
|
68
|
+
slave_stats.each do |key, value|
|
69
|
+
results << "\t#{key}: #{value}" unless key == :slave
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
results << "Total Examples: #{@master.stats[:examples]}"
|
74
|
+
results << "Total Pending: #{@master.stats[:pending]}"
|
75
|
+
results << "Total Failures: #{@master.stats[:failures]}"
|
76
|
+
results << ''
|
77
|
+
results << "Buffet consumed in #{@master.stats[:total_time]} seconds"
|
78
|
+
|
79
|
+
unless @master.failures.empty?
|
80
|
+
results << ''
|
81
|
+
results << @master.failures.map do |failure|
|
82
|
+
"#{failure[:description]}\n".red +
|
83
|
+
"Slave: #{failure[:slave_name]}\n" +
|
84
|
+
"Location: #{failure[:location]}\n" +
|
85
|
+
"#{failure[:message]}\n" +
|
86
|
+
"#{failure[:backtrace]}\n"
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
puts results
|
91
|
+
end
|
92
|
+
end
|
93
|
+
end
|
@@ -0,0 +1,58 @@
|
|
1
|
+
require 'yaml'
|
2
|
+
|
3
|
+
module Buffet
|
4
|
+
class Settings
|
5
|
+
DEFAULT_SETTINGS_FILE = 'buffet.yml'
|
6
|
+
DEFAULT_PREPARE_SCRIPT = 'bin/before-buffet-run'
|
7
|
+
DEFAULT_EXCLUDE_FILTER_FILE = '.buffet-exclude-filter'
|
8
|
+
|
9
|
+
class << self
|
10
|
+
def [](name)
|
11
|
+
@settings ||= load_file DEFAULT_SETTINGS_FILE
|
12
|
+
@settings[name]
|
13
|
+
end
|
14
|
+
|
15
|
+
def load_file file
|
16
|
+
@settings = YAML.load_file file
|
17
|
+
end
|
18
|
+
|
19
|
+
def slaves
|
20
|
+
@slaves ||= self['slaves'].map do |slave_hash|
|
21
|
+
Slave.new slave_hash['user'], slave_hash['host'], project
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
def project_name=(project_name)
|
26
|
+
project.name = project_name
|
27
|
+
end
|
28
|
+
|
29
|
+
def project
|
30
|
+
@project ||= Project.new Dir.pwd
|
31
|
+
end
|
32
|
+
|
33
|
+
def framework
|
34
|
+
self['framework'].upcase || 'RSPEC1'
|
35
|
+
end
|
36
|
+
|
37
|
+
def prepare_script
|
38
|
+
self['prepare_script'] || DEFAULT_PREPARE_SCRIPT
|
39
|
+
end
|
40
|
+
|
41
|
+
def has_prepare_script?
|
42
|
+
self['prepare_script'] || File.exist?(DEFAULT_PREPARE_SCRIPT)
|
43
|
+
end
|
44
|
+
|
45
|
+
def exclude_filter_file
|
46
|
+
self['exclude_filter_file'] || DEFAULT_EXCLUDE_FILTER_FILE
|
47
|
+
end
|
48
|
+
|
49
|
+
def has_exclude_filter_file?
|
50
|
+
self['exclude_filter_file'] || File.exist?(DEFAULT_EXCLUDE_FILTER_FILE)
|
51
|
+
end
|
52
|
+
|
53
|
+
def reset!
|
54
|
+
@settings = nil
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
data/lib/buffet/slave.rb
ADDED
@@ -0,0 +1,48 @@
|
|
1
|
+
module Buffet
|
2
|
+
class Slave
|
3
|
+
attr_reader :user, :host
|
4
|
+
|
5
|
+
def initialize user, host, project
|
6
|
+
@user = user
|
7
|
+
@host = host
|
8
|
+
@project = project
|
9
|
+
end
|
10
|
+
|
11
|
+
def rsync src, dest
|
12
|
+
Buffet.run! 'rsync', '-aqz', '--delete',
|
13
|
+
'--delete-excluded', rsync_exclude_flags,
|
14
|
+
'-e', 'ssh', src, "#{user_at_host}:#{dest}"
|
15
|
+
end
|
16
|
+
|
17
|
+
def scp src, dest, options = {}
|
18
|
+
args = [src, "#{user_at_host}:#{dest}"]
|
19
|
+
args.unshift '-r' if options[:recurse]
|
20
|
+
Buffet.run! 'scp', *args
|
21
|
+
end
|
22
|
+
|
23
|
+
def execute_in_project command
|
24
|
+
execute "cd #{@project.directory_on_slave} && #{command}"
|
25
|
+
end
|
26
|
+
|
27
|
+
def execute command
|
28
|
+
Buffet.run! 'ssh', "#{user_at_host}", command
|
29
|
+
end
|
30
|
+
|
31
|
+
def name
|
32
|
+
user_at_host
|
33
|
+
end
|
34
|
+
|
35
|
+
def user_at_host
|
36
|
+
"#{@user}@#{@host}"
|
37
|
+
end
|
38
|
+
|
39
|
+
private
|
40
|
+
|
41
|
+
def rsync_exclude_flags
|
42
|
+
if Settings.has_exclude_filter_file?
|
43
|
+
exclude_flags = "--exclude-from=#{Settings.exclude_filter_file}"
|
44
|
+
end
|
45
|
+
exclude_flags || ''
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
data/lib/buffet.rb
ADDED
@@ -0,0 +1,60 @@
|
|
1
|
+
require 'fileutils'
|
2
|
+
require 'find'
|
3
|
+
require 'logger'
|
4
|
+
require 'pathname'
|
5
|
+
|
6
|
+
module Buffet
|
7
|
+
autoload :CommandRunner, 'buffet/command_runner'
|
8
|
+
autoload :Master, 'buffet/master'
|
9
|
+
autoload :Project, 'buffet/project'
|
10
|
+
autoload :Runner, 'buffet/runner'
|
11
|
+
autoload :Settings, 'buffet/settings'
|
12
|
+
autoload :Slave, 'buffet/slave'
|
13
|
+
|
14
|
+
def self.logdir
|
15
|
+
@logdir ||= Pathname.new(ENV['HOME']) + '.buffet/log'
|
16
|
+
end
|
17
|
+
|
18
|
+
def self.logfile
|
19
|
+
'buffet.log'
|
20
|
+
end
|
21
|
+
|
22
|
+
def self.logger
|
23
|
+
@logger ||= begin
|
24
|
+
FileUtils.mkdir_p logdir
|
25
|
+
Logger.new logdir + logfile
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def self.runner
|
30
|
+
@runner ||= CommandRunner.new logger
|
31
|
+
end
|
32
|
+
|
33
|
+
def self.run! *command
|
34
|
+
result = runner.run *command
|
35
|
+
unless result.success?
|
36
|
+
logger.error 'exiting due to non-zero exit status'
|
37
|
+
exit result.status
|
38
|
+
end
|
39
|
+
result
|
40
|
+
end
|
41
|
+
|
42
|
+
# Given a set of files/directories, return all spec files contained
|
43
|
+
def self.extract_specs_from files
|
44
|
+
specs = []
|
45
|
+
files.each do |spec_file|
|
46
|
+
Find.find(spec_file) do |f|
|
47
|
+
specs << f if f.match /_spec\.rb$/
|
48
|
+
end
|
49
|
+
end
|
50
|
+
specs.uniq
|
51
|
+
end
|
52
|
+
|
53
|
+
def self.workspace_dir
|
54
|
+
".buffet/workspaces/#{user}" # Relative to home directory
|
55
|
+
end
|
56
|
+
|
57
|
+
def self.user
|
58
|
+
@user ||= `whoami`.chomp
|
59
|
+
end
|
60
|
+
end
|
@@ -0,0 +1,52 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require 'drb'
|
4
|
+
require 'fileutils'
|
5
|
+
|
6
|
+
if File.exist? 'Gemfile'
|
7
|
+
require 'rubygems'
|
8
|
+
require 'bundler/setup'
|
9
|
+
end
|
10
|
+
|
11
|
+
# NOTE: ARGV is used by the spec runner. If I leave the drb server address
|
12
|
+
# in ARGV, rspec will think it's an argument to the test runner.
|
13
|
+
buffet_server = DRbObject.new_with_uri(ARGV.shift)
|
14
|
+
slave_name = ARGV.shift
|
15
|
+
framework = ARGV.shift
|
16
|
+
|
17
|
+
FileUtils.mkdir_p('./tmp')
|
18
|
+
|
19
|
+
if framework == 'RSPEC1'
|
20
|
+
require 'spec'
|
21
|
+
require 'spec/runner/command_line'
|
22
|
+
require File.dirname(__FILE__) + '/rspec1_formatter.rb'
|
23
|
+
|
24
|
+
Spec::Runner::Formatter::AugmentedTextFormatter.configure buffet_server, slave_name
|
25
|
+
|
26
|
+
while file = buffet_server.next_file_for(slave_name)
|
27
|
+
# RSpec1 closes stderr/out after each run, so we reopen them each time
|
28
|
+
outlog = File.open('./tmp/buffet.out.log', 'a')
|
29
|
+
errlog = File.open('./tmp/buffet.error.log', 'a')
|
30
|
+
|
31
|
+
Spec::Runner::CommandLine.run(
|
32
|
+
Spec::Runner::OptionParser.parse(
|
33
|
+
['--format', 'Spec::Runner::Formatter::AugmentedTextFormatter', file],
|
34
|
+
errlog,
|
35
|
+
outlog
|
36
|
+
)
|
37
|
+
)
|
38
|
+
end
|
39
|
+
else
|
40
|
+
require 'rspec'
|
41
|
+
require File.dirname(__FILE__) + '/rspec2_formatter.rb'
|
42
|
+
|
43
|
+
RSpec::Core::Formatters::AugmentedTextFormatter.configure buffet_server, slave_name
|
44
|
+
|
45
|
+
while file = buffet_server.next_file_for(slave_name)
|
46
|
+
RSpec::Core::CommandLine.new(
|
47
|
+
['--format', 'RSpec::Core::Formatters::AugmentedTextFormatter', file]
|
48
|
+
).run($stderr, $stdout)
|
49
|
+
|
50
|
+
RSpec.world.reset
|
51
|
+
end
|
52
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
require 'spec/runner/formatter/base_text_formatter'
|
2
|
+
|
3
|
+
module Spec
|
4
|
+
module Runner
|
5
|
+
module Formatter
|
6
|
+
class AugmentedTextFormatter < BaseTextFormatter
|
7
|
+
def self.configure buffet_server, slave_name
|
8
|
+
@@buffet_server = buffet_server
|
9
|
+
@@slave_name = slave_name
|
10
|
+
end
|
11
|
+
|
12
|
+
def example_passed example_proxy
|
13
|
+
super
|
14
|
+
@@buffet_server.example_passed(@@slave_name, {
|
15
|
+
:description => example_proxy.description,
|
16
|
+
:location => example_proxy.location,
|
17
|
+
:slave_name => @@slave_name,
|
18
|
+
})
|
19
|
+
end
|
20
|
+
|
21
|
+
def example_failed example_proxy, counter, failure
|
22
|
+
super
|
23
|
+
@@buffet_server.example_failed(@@slave_name, {
|
24
|
+
:backtrace => failure.exception.backtrace.join("\n"),
|
25
|
+
:description => failure.header,
|
26
|
+
:location => example_proxy.location,
|
27
|
+
:message => failure.exception.message,
|
28
|
+
:slave_name => @@slave_name,
|
29
|
+
})
|
30
|
+
end
|
31
|
+
|
32
|
+
def example_pending example, message, deprecated_pending_location=nil
|
33
|
+
super
|
34
|
+
@@buffet_server.example_pending(@@slave_name, {
|
35
|
+
:description => example.description,
|
36
|
+
:location => example.location,
|
37
|
+
:message => message,
|
38
|
+
:slave_name => @@slave_name,
|
39
|
+
})
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
require 'rspec/core/formatters/base_text_formatter'
|
2
|
+
|
3
|
+
module RSpec
|
4
|
+
module Core
|
5
|
+
module Formatters
|
6
|
+
class AugmentedTextFormatter < BaseTextFormatter
|
7
|
+
def initialize(output)
|
8
|
+
super(output)
|
9
|
+
end
|
10
|
+
|
11
|
+
def self.configure buffet_server, slave_name
|
12
|
+
@@buffet_server = buffet_server
|
13
|
+
@@slave_name = slave_name
|
14
|
+
end
|
15
|
+
|
16
|
+
def example_passed example
|
17
|
+
super
|
18
|
+
@@buffet_server.example_passed(@@slave_name, {
|
19
|
+
:description => example.description,
|
20
|
+
:location => example.location,
|
21
|
+
:slave_name => slave_name,
|
22
|
+
})
|
23
|
+
end
|
24
|
+
|
25
|
+
def example_failed example
|
26
|
+
super
|
27
|
+
exception = example.metadata[:execution_result][:exception]
|
28
|
+
backtrace = format_backtrace(exception.backtrace, example).join("\n")
|
29
|
+
|
30
|
+
@@buffet_server.example_failed(@@slave_name, {
|
31
|
+
:description => description,
|
32
|
+
:backtrace => backtrace,
|
33
|
+
:message => exception.message,
|
34
|
+
:location => example.location,
|
35
|
+
:slave_name => slave_name,
|
36
|
+
})
|
37
|
+
end
|
38
|
+
|
39
|
+
def example_pending example, message, deprecated_pending_location=nil
|
40
|
+
super
|
41
|
+
@@buffet_server.example_pending(@@slave_name, {
|
42
|
+
:description => example.description,
|
43
|
+
:location => example.location,
|
44
|
+
:message => message,
|
45
|
+
:slave_name => slave_name,
|
46
|
+
})
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
metadata
ADDED
@@ -0,0 +1,122 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: minimal-buffet
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
prerelease: false
|
5
|
+
segments:
|
6
|
+
- 0
|
7
|
+
- 6
|
8
|
+
version: "0.6"
|
9
|
+
platform: ruby
|
10
|
+
authors:
|
11
|
+
- Causes Engineering
|
12
|
+
autorequire:
|
13
|
+
bindir: bin
|
14
|
+
cert_chain: []
|
15
|
+
|
16
|
+
date: 2011-12-29 00:00:00 -05:00
|
17
|
+
default_executable:
|
18
|
+
dependencies:
|
19
|
+
- !ruby/object:Gem::Dependency
|
20
|
+
name: colorize
|
21
|
+
prerelease: false
|
22
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ">="
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
segments:
|
27
|
+
- 0
|
28
|
+
version: "0"
|
29
|
+
type: :runtime
|
30
|
+
version_requirements: *id001
|
31
|
+
- !ruby/object:Gem::Dependency
|
32
|
+
name: wopen3
|
33
|
+
prerelease: false
|
34
|
+
requirement: &id002 !ruby/object:Gem::Requirement
|
35
|
+
requirements:
|
36
|
+
- - ">="
|
37
|
+
- !ruby/object:Gem::Version
|
38
|
+
segments:
|
39
|
+
- 0
|
40
|
+
version: "0"
|
41
|
+
type: :runtime
|
42
|
+
version_requirements: *id002
|
43
|
+
- !ruby/object:Gem::Dependency
|
44
|
+
name: rspec
|
45
|
+
prerelease: false
|
46
|
+
requirement: &id003 !ruby/object:Gem::Requirement
|
47
|
+
requirements:
|
48
|
+
- - ">="
|
49
|
+
- !ruby/object:Gem::Version
|
50
|
+
segments:
|
51
|
+
- 0
|
52
|
+
version: "0"
|
53
|
+
type: :development
|
54
|
+
version_requirements: *id003
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: mkdtemp
|
57
|
+
prerelease: false
|
58
|
+
requirement: &id004 !ruby/object:Gem::Requirement
|
59
|
+
requirements:
|
60
|
+
- - ">="
|
61
|
+
- !ruby/object:Gem::Version
|
62
|
+
segments:
|
63
|
+
- 0
|
64
|
+
version: "0"
|
65
|
+
type: :development
|
66
|
+
version_requirements: *id004
|
67
|
+
description: Buffet distributes RSpec test cases over multiple machines.
|
68
|
+
email:
|
69
|
+
- eng@causes.com
|
70
|
+
- grant@causes.com
|
71
|
+
- shane@causes.com
|
72
|
+
executables:
|
73
|
+
- buffet
|
74
|
+
extensions: []
|
75
|
+
|
76
|
+
extra_rdoc_files: []
|
77
|
+
|
78
|
+
files:
|
79
|
+
- lib/buffet.rb
|
80
|
+
- lib/buffet/cli.rb
|
81
|
+
- lib/buffet/command_runner.rb
|
82
|
+
- lib/buffet/master.rb
|
83
|
+
- lib/buffet/project.rb
|
84
|
+
- lib/buffet/runner.rb
|
85
|
+
- lib/buffet/settings.rb
|
86
|
+
- lib/buffet/slave.rb
|
87
|
+
- lib/buffet/version.rb
|
88
|
+
- support/buffet-worker
|
89
|
+
- support/rspec1_formatter.rb
|
90
|
+
- support/rspec2_formatter.rb
|
91
|
+
has_rdoc: true
|
92
|
+
homepage: http://github.com/causes/buffet
|
93
|
+
licenses: []
|
94
|
+
|
95
|
+
post_install_message:
|
96
|
+
rdoc_options: []
|
97
|
+
|
98
|
+
require_paths:
|
99
|
+
- lib
|
100
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
101
|
+
requirements:
|
102
|
+
- - ">="
|
103
|
+
- !ruby/object:Gem::Version
|
104
|
+
segments:
|
105
|
+
- 0
|
106
|
+
version: "0"
|
107
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
108
|
+
requirements:
|
109
|
+
- - ">="
|
110
|
+
- !ruby/object:Gem::Version
|
111
|
+
segments:
|
112
|
+
- 0
|
113
|
+
version: "0"
|
114
|
+
requirements: []
|
115
|
+
|
116
|
+
rubyforge_project:
|
117
|
+
rubygems_version: 1.3.6
|
118
|
+
signing_key:
|
119
|
+
specification_version: 3
|
120
|
+
summary: Distributed testing framework for Ruby, Rails and RSpec
|
121
|
+
test_files: []
|
122
|
+
|