specjour 0.7.0 → 2.0.0.rc1

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.
Files changed (49) hide show
  1. checksums.yaml +7 -0
  2. data/History.markdown +12 -0
  3. data/README.markdown +24 -1
  4. data/Rakefile +12 -12
  5. data/bin/specjour +3 -1
  6. data/lib/specjour/cli.rb +86 -110
  7. data/lib/specjour/colors.rb +23 -0
  8. data/lib/specjour/configuration.rb +47 -91
  9. data/lib/specjour/connection.rb +69 -20
  10. data/lib/specjour/cpu.rb +4 -0
  11. data/lib/specjour/fork.rb +1 -1
  12. data/lib/specjour/formatter.rb +153 -0
  13. data/lib/specjour/listener.rb +181 -0
  14. data/lib/specjour/loader.rb +55 -119
  15. data/lib/specjour/logger.rb +34 -0
  16. data/lib/specjour/plugin/base.rb +61 -0
  17. data/lib/specjour/plugin/manager.rb +28 -0
  18. data/lib/specjour/plugin/rails.rb +47 -0
  19. data/lib/specjour/plugin/rails_v3.rb +23 -0
  20. data/lib/specjour/plugin/rails_v4.rb +25 -0
  21. data/lib/specjour/plugin/rspec.rb +160 -0
  22. data/lib/specjour/plugin/rspec_v2.rb +53 -0
  23. data/lib/specjour/plugin/rspec_v3.rb +59 -0
  24. data/lib/specjour/plugin/ssh.rb +24 -0
  25. data/lib/specjour/plugin.rb +4 -0
  26. data/lib/specjour/printer.rb +235 -67
  27. data/lib/specjour/protocol.rb +13 -6
  28. data/lib/specjour/rspec_formatter.rb +17 -0
  29. data/lib/specjour/rsync_daemon.rb +6 -3
  30. data/lib/specjour/socket_helper.rb +26 -10
  31. data/lib/specjour/worker.rb +36 -62
  32. data/lib/specjour.rb +50 -24
  33. data/lib/specjour_plugin.rb +5 -0
  34. metadata +52 -84
  35. data/lib/specjour/cucumber/distributed_formatter.rb +0 -82
  36. data/lib/specjour/cucumber/final_report.rb +0 -83
  37. data/lib/specjour/cucumber/preloader.rb +0 -22
  38. data/lib/specjour/cucumber/runner.rb +0 -15
  39. data/lib/specjour/cucumber.rb +0 -16
  40. data/lib/specjour/db_scrub.rb +0 -56
  41. data/lib/specjour/dispatcher.rb +0 -170
  42. data/lib/specjour/manager.rb +0 -174
  43. data/lib/specjour/rspec/distributed_formatter.rb +0 -50
  44. data/lib/specjour/rspec/final_report.rb +0 -73
  45. data/lib/specjour/rspec/marshalable_exception.rb +0 -19
  46. data/lib/specjour/rspec/preloader.rb +0 -15
  47. data/lib/specjour/rspec/runner.rb +0 -14
  48. data/lib/specjour/rspec/shared_example_group_ext.rb +0 -9
  49. 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
@@ -0,0 +1,4 @@
1
+ module Specjour::Plugin
2
+ autoload :Manager, "specjour/plugin/manager"
3
+ autoload :Base, "specjour/plugin/base"
4
+ end