specjour 0.7.0 → 2.0.0.rc1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/History.markdown +12 -0
- data/README.markdown +24 -1
- data/Rakefile +12 -12
- data/bin/specjour +3 -1
- data/lib/specjour/cli.rb +86 -110
- data/lib/specjour/colors.rb +23 -0
- data/lib/specjour/configuration.rb +47 -91
- data/lib/specjour/connection.rb +69 -20
- data/lib/specjour/cpu.rb +4 -0
- data/lib/specjour/fork.rb +1 -1
- data/lib/specjour/formatter.rb +153 -0
- data/lib/specjour/listener.rb +181 -0
- data/lib/specjour/loader.rb +55 -119
- data/lib/specjour/logger.rb +34 -0
- data/lib/specjour/plugin/base.rb +61 -0
- data/lib/specjour/plugin/manager.rb +28 -0
- data/lib/specjour/plugin/rails.rb +47 -0
- data/lib/specjour/plugin/rails_v3.rb +23 -0
- data/lib/specjour/plugin/rails_v4.rb +25 -0
- data/lib/specjour/plugin/rspec.rb +160 -0
- data/lib/specjour/plugin/rspec_v2.rb +53 -0
- data/lib/specjour/plugin/rspec_v3.rb +59 -0
- data/lib/specjour/plugin/ssh.rb +24 -0
- data/lib/specjour/plugin.rb +4 -0
- data/lib/specjour/printer.rb +235 -67
- data/lib/specjour/protocol.rb +13 -6
- data/lib/specjour/rspec_formatter.rb +17 -0
- data/lib/specjour/rsync_daemon.rb +6 -3
- data/lib/specjour/socket_helper.rb +26 -10
- data/lib/specjour/worker.rb +36 -62
- data/lib/specjour.rb +50 -24
- data/lib/specjour_plugin.rb +5 -0
- metadata +52 -84
- data/lib/specjour/cucumber/distributed_formatter.rb +0 -82
- data/lib/specjour/cucumber/final_report.rb +0 -83
- data/lib/specjour/cucumber/preloader.rb +0 -22
- data/lib/specjour/cucumber/runner.rb +0 -15
- data/lib/specjour/cucumber.rb +0 -16
- data/lib/specjour/db_scrub.rb +0 -56
- data/lib/specjour/dispatcher.rb +0 -170
- data/lib/specjour/manager.rb +0 -174
- data/lib/specjour/rspec/distributed_formatter.rb +0 -50
- data/lib/specjour/rspec/final_report.rb +0 -73
- data/lib/specjour/rspec/marshalable_exception.rb +0 -19
- data/lib/specjour/rspec/preloader.rb +0 -15
- data/lib/specjour/rspec/runner.rb +0 -14
- data/lib/specjour/rspec/shared_example_group_ext.rb +0 -9
- data/lib/specjour/rspec.rb +0 -17
@@ -0,0 +1,47 @@
|
|
1
|
+
module Specjour::Plugin
|
2
|
+
|
3
|
+
class Rails < Base
|
4
|
+
|
5
|
+
def load_application
|
6
|
+
log "Loading rails plugin"
|
7
|
+
if File.exists?("./config/application.rb")
|
8
|
+
bundle_install
|
9
|
+
ENV["RAILS_ENV"] ||= "test"
|
10
|
+
require File.expand_path("config/application", Dir.pwd)
|
11
|
+
# require File.expand_path("config/environment", Dir.pwd)
|
12
|
+
@rails_loaded = true
|
13
|
+
Specjour.load_plugins
|
14
|
+
if ::Rails.version =~ /^4/
|
15
|
+
require "specjour/plugin/rails_v4.rb"
|
16
|
+
extend RailsV4
|
17
|
+
else
|
18
|
+
require "specjour/plugin/rails_v3.rb"
|
19
|
+
extend RailsV3
|
20
|
+
end
|
21
|
+
versioned_load_application
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
def before_worker_fork
|
26
|
+
return unless @rails_loaded
|
27
|
+
ActiveRecord::Base.remove_connection
|
28
|
+
end
|
29
|
+
|
30
|
+
protected
|
31
|
+
|
32
|
+
def force_task(task)
|
33
|
+
Rake::Task[task].invoke
|
34
|
+
rescue StandardError
|
35
|
+
end
|
36
|
+
|
37
|
+
def bundle_install
|
38
|
+
if system('which bundle')
|
39
|
+
system('bundle check') || system('bundle install')
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
def system(cmd)
|
44
|
+
Kernel.system("#{cmd} > /dev/null")
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
module Specjour
|
2
|
+
module Plugin
|
3
|
+
module RailsV3
|
4
|
+
|
5
|
+
def versioned_load_application
|
6
|
+
load "active_record/railties/databases.rake"
|
7
|
+
Rake::Task.define_task(:environment) unless Rake::Task.task_defined?(:environment)
|
8
|
+
Rake::Task.define_task(:rails_env) unless Rake::Task.task_defined?(:rails_env)
|
9
|
+
end
|
10
|
+
|
11
|
+
def after_worker_fork
|
12
|
+
return unless (defined?(::Rails) && defined?(::ActiveRecord::Base))
|
13
|
+
force_task('db:drop')
|
14
|
+
force_task('db:create')
|
15
|
+
Rake::Task[{ :sql => "db:test:load_structure", :ruby => "db:test:load" }[ActiveRecord::Base.schema_format]].invoke
|
16
|
+
ActiveRecord::Base.establish_connection
|
17
|
+
ActiveRecord::Base.connection.schema_cache.clear!
|
18
|
+
ActiveRecord::Base.descendants.each {|m| m.reset_column_information}
|
19
|
+
end
|
20
|
+
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
module Specjour
|
2
|
+
module Plugin
|
3
|
+
module RailsV4
|
4
|
+
|
5
|
+
def versioned_load_application
|
6
|
+
# require File.expand_path("config/environment", Dir.pwd)
|
7
|
+
load "active_record/railties/databases.rake"
|
8
|
+
ActiveRecord::Tasks::DatabaseTasks.database_configuration = ::Rails.application.config.database_configuration
|
9
|
+
require "rails/tasks"
|
10
|
+
end
|
11
|
+
|
12
|
+
def after_worker_fork
|
13
|
+
return unless (defined?(::Rails) && defined?(::ActiveRecord::Base))
|
14
|
+
ActiveRecord::Tasks::DatabaseTasks.database_configuration = ::Rails.application.config.database_configuration
|
15
|
+
ActiveRecord::Base.establish_connection
|
16
|
+
force_task('db:drop')
|
17
|
+
force_task('db:create')
|
18
|
+
Rake::Task[{ :sql => "db:structure:load", :ruby => "db:schema:load" }[ActiveRecord::Base.schema_format]].invoke
|
19
|
+
ActiveRecord::Base.connection.schema_cache.clear!
|
20
|
+
ActiveRecord::Base.descendants.each {|m| m.reset_column_information}
|
21
|
+
end
|
22
|
+
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,160 @@
|
|
1
|
+
module Specjour
|
2
|
+
module Plugin
|
3
|
+
class RSpec < Base
|
4
|
+
|
5
|
+
|
6
|
+
FILE_RE = /_spec\.rb/
|
7
|
+
|
8
|
+
Specjour::Configuration.make_option(:rspec_rerun)
|
9
|
+
Specjour.configuration.rspec_rerun = true
|
10
|
+
|
11
|
+
attr_reader :rerunner
|
12
|
+
|
13
|
+
def initialize
|
14
|
+
@all_specs = {}
|
15
|
+
end
|
16
|
+
|
17
|
+
def interrupted!
|
18
|
+
if defined?(::RSpec)
|
19
|
+
::RSpec.world.wants_to_quit = true
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def load_application
|
24
|
+
log "application loading from RSpec plugin #{Dir.pwd}"
|
25
|
+
require "rspec/core"
|
26
|
+
|
27
|
+
::RSpec::Core::Runner.disable_autorun!
|
28
|
+
@output = connection
|
29
|
+
::RSpec.configuration.error_stream = $stderr
|
30
|
+
::RSpec.configuration.output_stream = @output
|
31
|
+
|
32
|
+
if ::RSpec::Core::Version::STRING =~ /^3\./
|
33
|
+
require "specjour/plugin/rspec_v3"
|
34
|
+
extend Specjour::Plugin::RSpecV3
|
35
|
+
else
|
36
|
+
require "specjour/plugin/rspec_v2"
|
37
|
+
extend Specjour::Plugin::RSpecV2
|
38
|
+
end
|
39
|
+
|
40
|
+
versioned_load_application
|
41
|
+
end
|
42
|
+
|
43
|
+
def register_tests_with_printer
|
44
|
+
connection.register_tests rspec_examples
|
45
|
+
end
|
46
|
+
|
47
|
+
def run_test(test)
|
48
|
+
run(test) if FILE_RE === test
|
49
|
+
true
|
50
|
+
end
|
51
|
+
|
52
|
+
def after_print_summary(formatter)
|
53
|
+
if formatter.failures.any? && !Specjour.interrupted?
|
54
|
+
@rerunner = ReRunner.new(formatter)
|
55
|
+
rerunner.start
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
def exit_status(formatter)
|
60
|
+
if formatter.failures.any?
|
61
|
+
rerunner.exit_status
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
protected
|
66
|
+
|
67
|
+
def find_example(all_examples)
|
68
|
+
::RSpec.configuration.filter_manager.prune all_examples
|
69
|
+
end
|
70
|
+
|
71
|
+
def rspec_examples
|
72
|
+
if spec_files.any?
|
73
|
+
file_names_with_location
|
74
|
+
else
|
75
|
+
[]
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
def spec_files
|
80
|
+
return @spec_files if instance_variable_defined?(:@spec_files)
|
81
|
+
if Specjour.configuration.test_paths.empty?
|
82
|
+
@spec_files = Dir["spec/**/*_spec.rb"]
|
83
|
+
else
|
84
|
+
@spec_files = Specjour.configuration.test_paths.map do |test_path|
|
85
|
+
if File.basename(test_path) != Specjour.configuration.project_path
|
86
|
+
if File.directory?(test_path)
|
87
|
+
Dir["#{test_path}/**/*_spec.rb"]
|
88
|
+
else
|
89
|
+
test_path
|
90
|
+
end
|
91
|
+
# Dir[test_path, "#{test_path}/**/*_spec.rb"]
|
92
|
+
end
|
93
|
+
end.flatten.compact.uniq
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
def file_names_with_location
|
98
|
+
executables = gather_groups(::RSpec.world.example_groups)
|
99
|
+
locations = executables.map do |e|
|
100
|
+
if e.respond_to?(:examples)
|
101
|
+
e.metadata[:example_group][:location]
|
102
|
+
else
|
103
|
+
if e.example_group.metadata[:shared_group_name]
|
104
|
+
e.metadata[:example_group][:location]
|
105
|
+
else
|
106
|
+
e.metadata[:location]
|
107
|
+
end
|
108
|
+
end
|
109
|
+
end
|
110
|
+
locations.map.with_index do |location, i|
|
111
|
+
@all_specs[location] ||= []
|
112
|
+
executable = executables[i]
|
113
|
+
@all_specs[location] << executable
|
114
|
+
end
|
115
|
+
locations
|
116
|
+
end
|
117
|
+
|
118
|
+
class ReRunner
|
119
|
+
|
120
|
+
include Colors
|
121
|
+
|
122
|
+
attr_reader :formatter, :exit_status
|
123
|
+
|
124
|
+
def initialize(formatter)
|
125
|
+
@formatter = formatter
|
126
|
+
@exit_status = false
|
127
|
+
end
|
128
|
+
|
129
|
+
def start
|
130
|
+
if Specjour.configuration.rspec_rerun
|
131
|
+
rerun
|
132
|
+
else
|
133
|
+
print_rerun
|
134
|
+
end
|
135
|
+
end
|
136
|
+
|
137
|
+
def rerun
|
138
|
+
command = "rake db:test:prepare && #{rerun_command}"
|
139
|
+
output.puts("Rerunning failing tests with following command:\n#{command}")
|
140
|
+
@exit_status = system(command)
|
141
|
+
end
|
142
|
+
|
143
|
+
def print_rerun
|
144
|
+
cmd = colorize(rerun_command, :red)
|
145
|
+
output.puts "Rerun failures with this command:\n\n#{cmd}"
|
146
|
+
end
|
147
|
+
|
148
|
+
def rerun_command
|
149
|
+
"rspec #{formatter.failing_test_paths.select {|t| RSpec::FILE_RE === t}.join(" ")}"
|
150
|
+
end
|
151
|
+
|
152
|
+
def output
|
153
|
+
formatter.output
|
154
|
+
end
|
155
|
+
|
156
|
+
end
|
157
|
+
|
158
|
+
end
|
159
|
+
end
|
160
|
+
end
|
@@ -0,0 +1,53 @@
|
|
1
|
+
module Specjour
|
2
|
+
module Plugin
|
3
|
+
module RSpecV2
|
4
|
+
|
5
|
+
def versioned_load_application
|
6
|
+
@configuration_options = ::RSpec::Core::ConfigurationOptions.new([spec_files])
|
7
|
+
@configuration_options.parse_options
|
8
|
+
@configuration_options.configure ::RSpec.configuration
|
9
|
+
::RSpec.configuration.load_spec_files
|
10
|
+
end
|
11
|
+
|
12
|
+
def before_suite
|
13
|
+
::RSpec.configuration.run_hook(:before, :suite)
|
14
|
+
end
|
15
|
+
|
16
|
+
def after_suite
|
17
|
+
::RSpec.configuration.run_hook(:after, :suite)
|
18
|
+
end
|
19
|
+
|
20
|
+
def run(test)
|
21
|
+
::RSpec.configuration.reset
|
22
|
+
::RSpec.configuration.add_formatter(Specjour::RspecFormatter)
|
23
|
+
::RSpec.configuration.reporter.report(1, nil) do |reporter|
|
24
|
+
examples_or_groups = @all_specs[test]
|
25
|
+
examples_or_groups.each do |example_or_group|
|
26
|
+
if example_or_group.respond_to?(:example_group)
|
27
|
+
example = example_or_group
|
28
|
+
instance = example.example_group.new
|
29
|
+
example.run instance, reporter
|
30
|
+
else
|
31
|
+
example_or_group.run(reporter)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
# recursively gather groups containing a before(:all) hook, and examples
|
38
|
+
def gather_groups(groups)
|
39
|
+
groups.map do |g|
|
40
|
+
before_all_hooks = g.send(:find_hook, :before, :all, nil, nil)
|
41
|
+
if g.metadata.has_key?(:shared_group_name)
|
42
|
+
g
|
43
|
+
elsif before_all_hooks.any?
|
44
|
+
g
|
45
|
+
else
|
46
|
+
(g.filtered_examples || []) + gather_groups(g.children)
|
47
|
+
end
|
48
|
+
end.compact.flatten
|
49
|
+
end
|
50
|
+
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
@@ -0,0 +1,59 @@
|
|
1
|
+
module Specjour
|
2
|
+
module Plugin
|
3
|
+
module RSpecV3
|
4
|
+
|
5
|
+
::RSpec::Core::Formatters.register Specjour::RspecFormatter, :message, :dump_summary, :dump_profile, :stop, :close
|
6
|
+
|
7
|
+
def versioned_load_application
|
8
|
+
# require File.expand_path("spec/rails_helper", Dir.pwd)
|
9
|
+
@configuration_options = ::RSpec::Core::ConfigurationOptions.new([spec_files])
|
10
|
+
@configuration_options.configure ::RSpec.configuration
|
11
|
+
::RSpec.configuration.load_spec_files
|
12
|
+
end
|
13
|
+
|
14
|
+
def before_suite
|
15
|
+
::RSpec.configuration.instance_eval do
|
16
|
+
run_hooks_with(@before_suite_hooks, ::RSpec::Core::SuiteHookContext.new)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def after_suite
|
21
|
+
::RSpec.configuration.instance_eval do
|
22
|
+
run_hooks_with(@after_suite_hooks, ::RSpec::Core::SuiteHookContext.new)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
def run(test)
|
27
|
+
::RSpec.configuration.reset
|
28
|
+
::RSpec.configuration.default_formatter = Specjour::RspecFormatter
|
29
|
+
::RSpec.configuration.reporter.report(1) do |reporter|
|
30
|
+
examples_or_groups = @all_specs[test]
|
31
|
+
examples_or_groups.each do |example_or_group|
|
32
|
+
if example_or_group.respond_to?(:example_group_instance)
|
33
|
+
example = example_or_group
|
34
|
+
instance = example.example_group.new
|
35
|
+
example.run instance, reporter
|
36
|
+
else
|
37
|
+
example_or_group.run(reporter)
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
# recursively gather groups containing a before(:all) hook, and examples
|
44
|
+
def gather_groups(groups)
|
45
|
+
groups.map do |g|
|
46
|
+
before_all_hooks = g.hooks.send(:matching_hooks_for, :before, :all, g)
|
47
|
+
if g.metadata.has_key?(:shared_group_name)
|
48
|
+
g
|
49
|
+
elsif before_all_hooks.any?
|
50
|
+
g
|
51
|
+
else
|
52
|
+
(g.filtered_examples || []) + gather_groups(g.children)
|
53
|
+
end
|
54
|
+
end.compact.flatten
|
55
|
+
end
|
56
|
+
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
module Specjour
|
2
|
+
module Plugin
|
3
|
+
class SSH < Base
|
4
|
+
def initialize
|
5
|
+
|
6
|
+
end
|
7
|
+
|
8
|
+
def after_loader_fork
|
9
|
+
# hosts.each do |host|
|
10
|
+
# host.connect
|
11
|
+
# host.rsync
|
12
|
+
# host.load_plugins
|
13
|
+
# host.load_application
|
14
|
+
# host.launch_workers
|
15
|
+
# host.proxy_tests!
|
16
|
+
# end
|
17
|
+
#
|
18
|
+
# ssh host specjour launch an ssh loader
|
19
|
+
# specjour loader -h localhost:2000
|
20
|
+
#
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|