flatware-rspec 1.2.0 → 2.0.0.rc1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 9a2796efde9648f14e67263880f8b882c83b0a4abc7c1216bc72653656bf2602
4
- data.tar.gz: c56a0bcf090b321ecc4c61f39434d82c5d8d0bd64948732a4c6f8486f63452b4
3
+ metadata.gz: e6a0aaa1271e9e220195b1198be4374e2a3e0a40fbe0dbdb61fad0c4735ab4e0
4
+ data.tar.gz: 2e16cb3d10ac6a990a393b84e0a3ae04ea4ccccfdbb9de3d1b264d4729a2d32f
5
5
  SHA512:
6
- metadata.gz: 393b882ed325b4ac152f3f7c4850b98b9705fe38fcb99f5582cdf32ec4976b3222bbc0bd3432173d259fa6dcb3384c406ff5f0e64de0b3e9f950345bae052dd3
7
- data.tar.gz: 351ea03efe3feec52e9fd4dc5e8ac563b8e210e862e064f208e10960d07cd4edbd325812eeefb3be165d2f0cabf5db29e90638b9b720641474d0bf579b983c03
6
+ metadata.gz: 2b133ea289d7abe6828bf0c7188bb389c113126ea8e79866aed5b973d4213b473f79e219c4f3d151f6c1bbf175fd48790140c531c6ce4eeb488837c4bd1ed618
7
+ data.tar.gz: 26d0a1a2a322ee2ad2cb4ac9b5d33c42aefdbe15a80d1c108d8e7d8b11a4f50e8bfb36e8003496c3215c939c74c3797f1eca7dad0c11843d96d1e9e1f3f85c3c
data/README.md CHANGED
@@ -7,39 +7,6 @@
7
7
 
8
8
  Flatware parallelizes your test suite to significantly reduce test time.
9
9
 
10
- ## Requirements
11
-
12
- * ZeroMQ > 4.0
13
-
14
- ## Installation
15
-
16
- ### ZeroMQ
17
-
18
- #### Linux Ubuntu
19
-
20
- ```sh
21
- sudo apt-get install -qq libzmq3-dev
22
- ```
23
-
24
- (Never you mind the 3. This package contains ZMQ version 4.)
25
-
26
- #### Mac OSX
27
-
28
-
29
- If you're on macOS 10.12, use the custom hashrocket ZMQ homebrew formula.
30
-
31
- ```sh
32
- brew tap hashrocket/formulas
33
- brew install hashrocket/formulas/zeromq
34
- ```
35
-
36
- The stock homebrew version will likely work on older versions of macOS.
37
-
38
-
39
- ```sh
40
- brew install zeromq
41
- ```
42
-
43
10
  ### Flatware
44
11
 
45
12
  Add the runners you need to your Gemfile:
@@ -81,8 +48,9 @@ For this to work the configuration option must be loaded before any specs are ru
81
48
 
82
49
  --require spec_helper
83
50
 
84
- But beware, if you're using ActiveRecord in your suite you'll need to avoid doing things that cause it to establish a database connection in `spec_helper.rb`. If ActiveRecord connects before flatware forks off workers, each will die messily. All of this will just work if you're following [the recomended pattern of splitting your helpers into `spec_helper` and `rails_helper`](https://github.com/rspec/rspec-rails/blob/v3.8.2/lib/generators/rspec/install/templates/spec/rails_helper.rb).
85
-
51
+ But beware, if you're using ActiveRecord in your suite you'll need to avoid doing things that cause it to establish a database connection in `spec_helper.rb`. If ActiveRecord connects before flatware forks off workers, each will die messily. All of this will just work if you're following [the recomended pattern of splitting your helpers into `spec_helper` and `rails_helper`](https://github.com/rspec/rspec-rails/blob/v3.8.2/lib/generators/rspec/install/templates/spec/rails_helper.rb). Another option is to use [the configurable hooks](
52
+ #faster-startup-with-activerecord
53
+ ).
86
54
 
87
55
  ### Options
88
56
 
@@ -134,9 +102,31 @@ Now you are ready to rock:
134
102
  $ flatware rspec && flatware cucumber
135
103
  ```
136
104
 
137
- ## Planned Features
105
+ ### Faster Startup With ActiveRecord
106
+
107
+ Flatware has a couple lifecycle callbacks that you can use to avoid booting your app
108
+ over again on every core. One way to take advantage of this via a `spec/flatware_helper.rb` file like so:
138
109
 
139
- * Use heuristics to run your slowest tests first
110
+ ```ruby
111
+ Flatware.configure do |conf|
112
+ conf.before_fork do
113
+ require 'rails_helper'
114
+
115
+ ActiveRecord::Base.connection.disconnect!
116
+ end
117
+
118
+ conf.after_fork do |test_env_number|
119
+ config = ActiveRecord::Base.connection_config
120
+
121
+ ActiveRecord::Base.establish_connection(
122
+ config.merge(
123
+ database: config.fetch(:database) + test_env_number.to_s
124
+ )
125
+ )
126
+ end
127
+ end
128
+ ```
129
+ Now when I run `bundle exec flatware rspec -r ./spec/flatware_helper` My app only boots once, rather than once per core.
140
130
 
141
131
  ## Design Goals
142
132
 
@@ -167,20 +157,10 @@ directory. CD there and `flatware` will be in your path so you can tinker away.
167
157
 
168
158
  ## How it works
169
159
 
170
- Flatware relies on a message passing system to enable concurrency.
171
- The main process declares a worker for each cpu in the computer. Each
172
- worker forks from the main process and is then assigned a portion of the
173
- test suite. As the worker runs the test suite it sends progress
174
- messages to the main process. These messages are collected and when
175
- the last worker is finished the main process provides a report on the
176
- collected progress messages.
160
+ Flatware relies on a message passing system to enable concurrency. The main process forks a worker for each cpu in the computer. These workers are each given a chunk of the tests to run. The workers report back to the main process about their progress. The main process prints those progress messages. When the last worker is finished the main process prints the results.
177
161
 
178
162
  ## Resources
179
163
 
180
- To learn more about the messaging system that Flatware uses, take a look at the
181
- [excellent ZeroMQ guide][z].
182
-
183
- [z]: http://zguide.zeromq.org/page:all
184
164
  [a]: https://github.com/cucumber/aruba
185
165
 
186
166
  ## Contributing to Flatware
@@ -6,15 +6,16 @@ require 'flatware/rspec/cli'
6
6
 
7
7
  module Flatware
8
8
  module RSpec
9
- require 'flatware/rspec/formatters/console'
10
9
  require 'flatware/rspec/formatter'
11
10
  require 'flatware/rspec/job_builder'
12
11
 
13
- def self.extract_jobs_from_args(args, workers:)
12
+ module_function
13
+
14
+ def extract_jobs_from_args(args, workers:)
14
15
  JobBuilder.new(args, workers: workers).jobs
15
- end
16
+ end
16
17
 
17
- def self.run(job, _options = {})
18
+ def run(job, _options = {})
18
19
  runner = ::RSpec::Core::Runner
19
20
  def runner.trap_interrupt() end
20
21
 
@@ -1,28 +1,60 @@
1
- require 'flatware/rspec/examples_notification'
1
+ # frozen_string_literal: true
2
+
3
+ require 'forwardable'
4
+ require 'flatware/rspec/marshalable'
2
5
 
3
6
  module Flatware
4
7
  module RSpec
8
+ ##
9
+ # Marshalable container for the run details from a worker.
10
+ # Can be added to other checkpoints to create a final run summary.
5
11
  class Checkpoint
6
- attr_reader :summary, :failures_notification
12
+ extend Forwardable
13
+
14
+ def_delegator :summary, :failures?
15
+ def_delegators :failures_notification, :fully_formatted_failed_examples, :failure_notifications
16
+ def_delegators :pending_notification, :fully_formatted_pending_examples, :pending_examples
17
+
18
+ EVENTS = %i[dump_profile dump_summary dump_pending dump_failures].freeze
19
+
20
+ attr_reader :events
21
+
22
+ def initialize(events = {})
23
+ @events = events
24
+ end
7
25
 
8
- def initialize(summary, failures_notification)
9
- @summary, @failures_notification = summary, ExamplesNotification.new(failures_notification.failure_notifications)
26
+ EVENTS.each do |event|
27
+ define_method(event) do |notification|
28
+ events[event] = Marshalable.for_event(event).from_notification(notification)
29
+ end
10
30
  end
11
31
 
12
32
  def +(other)
13
- self.class.new summary + other.summary, failures_notification + other.failures_notification
33
+ self.class.new(
34
+ events.merge(other.events) { |_, event, other_event| event + other_event }
35
+ )
14
36
  end
15
37
 
16
38
  def failures?
17
- summary.failure_count > 0 || summary.errors_outside_of_examples_count > 0
39
+ summary.failures?
18
40
  end
19
41
 
20
- def failure_notifications
21
- failures_notification.failure_notifications
42
+ def summary
43
+ events.fetch(:dump_summary)
44
+ end
45
+
46
+ def profile
47
+ events[:dump_profile]
48
+ end
49
+
50
+ private
51
+
52
+ def failures_notification
53
+ events.fetch(:dump_failures)
22
54
  end
23
55
 
24
- def fully_formatted_failed_examples(*args)
25
- failures_notification.fully_formatted_failed_examples(*args)
56
+ def pending_notification
57
+ events.fetch(:dump_pending)
26
58
  end
27
59
  end
28
60
  end
@@ -1,16 +1,27 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'flatware/cli'
4
+ require 'flatware/rspec'
5
+ require 'flatware/rspec/formatters/console'
2
6
 
3
7
  module Flatware
8
+ # rspec thor command
4
9
  class CLI
5
10
  worker_option
6
- method_option 'dispatch-endpoint', type: :string, default: 'ipc://dispatch'
7
- method_option 'sink-endpoint', type: :string, default: 'ipc://task'
8
- desc "rspec [FLATWARE_OPTS]", "parallelizes rspec"
11
+ method_option(
12
+ 'sink-endpoint',
13
+ type: :string,
14
+ default: 'drbunix:sink'
15
+ )
16
+ desc 'rspec [FLATWARE_OPTS]', 'parallelizes rspec'
9
17
  def rspec(*rspec_args)
10
18
  jobs = RSpec.extract_jobs_from_args rspec_args, workers: workers
19
+ formatter = Flatware::RSpec::Formatters::Console.new($stdout, $stderr)
11
20
  Flatware.verbose = options[:log]
12
- Worker.spawn count: workers, runner: RSpec, dispatch: options['dispatch-endpoint'], sink: options['sink-endpoint']
13
- start_sink jobs: jobs, workers: workers, formatter: Flatware::RSpec::Formatters::Console.new($stdout, $stderr)
21
+ Worker.spawn count: workers, runner: RSpec, sink: options['sink-endpoint']
22
+ start_sink(jobs: jobs,
23
+ workers: workers,
24
+ formatter: formatter)
14
25
  end
15
26
  end
16
27
  end
@@ -1,50 +1,58 @@
1
1
  require 'flatware/rspec/checkpoint'
2
- require 'flatware/rspec/summary'
3
2
  require 'rspec/core/formatters/console_codes'
3
+ require 'forwardable'
4
4
 
5
5
  module Flatware
6
6
  module RSpec
7
7
  ProgressMessage = Struct.new(:progress)
8
8
 
9
9
  class Formatter
10
- attr_reader :summary, :output
10
+ extend Forwardable
11
+
12
+ def_delegators :@checkpoint, *Checkpoint::EVENTS
13
+
14
+ attr_reader :output
11
15
 
12
16
  def initialize(stdout)
13
17
  @output = stdout
14
18
  end
15
19
 
16
- def example_passed(example)
20
+ def example_passed(_example)
17
21
  send_progress :passed
18
22
  end
19
23
 
20
- def example_failed(example)
24
+ def example_failed(_example)
21
25
  send_progress :failed
22
26
  end
23
27
 
24
- def example_pending(example)
28
+ def example_pending(_example)
25
29
  send_progress :pending
26
30
  end
27
31
 
28
- def dump_summary(summary)
29
- @summary = Summary.from_notification(summary)
30
- end
31
-
32
- def dump_failures(failure_notification)
33
- @failure_notification = failure_notification
32
+ def start_dump(*)
33
+ @checkpoint = Checkpoint.new
34
34
  end
35
35
 
36
36
  def close(*)
37
- Sink::client.checkpoint Checkpoint.new(summary, @failure_notification)
38
- @failure_notification = nil
37
+ Sink.client.checkpoint @checkpoint
38
+ @checkpoint = nil
39
39
  end
40
40
 
41
41
  private
42
42
 
43
43
  def send_progress(status)
44
- Sink::client.progress ProgressMessage.new status
44
+ Sink.client.progress ProgressMessage.new status
45
45
  end
46
46
  end
47
47
 
48
- ::RSpec::Core::Formatters.register Formatter, :example_passed, :example_failed, :example_pending, :dump_summary, :dump_failures, :close
48
+ ::RSpec::Core::Formatters.register(
49
+ Formatter,
50
+ *Checkpoint::EVENTS,
51
+ :example_passed,
52
+ :example_failed,
53
+ :example_pending,
54
+ :start_dump,
55
+ :close
56
+ )
49
57
  end
50
58
  end
@@ -1,33 +1,69 @@
1
- module Flatware::RSpec::Formatters
2
- class Console
3
- attr_reader :formatter
4
-
5
- def initialize(out, err)
6
- ::RSpec::configuration.tty = true
7
- ::RSpec::configuration.color = true
8
- @formatter = ::RSpec::Core::Formatters::ProgressFormatter.new(out)
9
- end
1
+ require 'rspec/core'
10
2
 
11
- def progress(result)
12
- formatter.send(message_for(result),nil)
13
- end
3
+ module Flatware
4
+ module RSpec
5
+ module Formatters
6
+ class Console
7
+ attr_reader :progress_formatter, :profile_formatter
14
8
 
15
- def summarize(checkpoints)
16
- result = checkpoints.reduce :+
17
- if result
18
- formatter.dump_failures result
19
- formatter.dump_summary result.summary
20
- end
21
- end
9
+ def initialize(out, _err)
10
+ ::RSpec.configuration.tty = true
11
+ ::RSpec.configuration.color = true
12
+ @progress_formatter = ::RSpec::Core::Formatters::ProgressFormatter.new(out)
13
+ @profile_formatter = ::RSpec::Core::Formatters::ProfileFormatter.new(out)
14
+ end
15
+
16
+ def progress(result)
17
+ progress_formatter.public_send(message_for(result), nil)
18
+ end
19
+
20
+ def summarize(checkpoints)
21
+ return if checkpoints.empty?
22
+
23
+ result = checkpoints.reduce :+
24
+
25
+ progress_formatter.dump_failures(result)
26
+ progress_formatter.dump_summary(result.summary)
27
+ profile_formatter.dump_profile(result.profile) if result.profile
28
+ progress_formatter.dump_pending(result) if result.pending_examples.any?
29
+ end
22
30
 
23
- private
31
+ def summarize_remaining(remaining)
32
+ progress_formatter.output.puts(colorizer.wrap(<<~MESSAGE, :detail))
24
33
 
25
- def message_for(result)
26
- {
27
- passed: :example_passed,
28
- failed: :example_failed,
29
- pending: :example_pending
30
- }.fetch result.progress
34
+ The following specs weren't run:
35
+
36
+ #{spec_list(remaining)}
37
+
38
+ MESSAGE
39
+ end
40
+
41
+ private
42
+
43
+ def spec_list(remaining)
44
+ remaining
45
+ .flat_map(&:id).sort.each_with_index
46
+ .map do |example, index|
47
+ format(
48
+ '%<index>4d) %<example>s',
49
+ index: index.next,
50
+ example: example
51
+ )
52
+ end.join("\n")
53
+ end
54
+
55
+ def colorizer
56
+ ::RSpec::Core::Formatters::ConsoleCodes
57
+ end
58
+
59
+ def message_for(result)
60
+ {
61
+ passed: :example_passed,
62
+ failed: :example_failed,
63
+ pending: :example_pending
64
+ }.fetch result.progress
65
+ end
66
+ end
31
67
  end
32
68
  end
33
69
  end
@@ -28,36 +28,39 @@ module Flatware
28
28
  end
29
29
 
30
30
  def jobs
31
- bucket_count = [files_to_run.size, workers].min
32
-
33
- seconds_per_file = load_persisted_example_statuses
34
- .select(&passing)
35
- .map(&parse_example)
36
- .reduce({}, &sum_by_example_file)
37
-
38
- timed_files, untimed_files = files_to_run
39
- .map(&method(:normalize_path))
40
- .reduce(
41
- [[], []]
42
- ) do |(timed, untimed), file|
43
- if (time = seconds_per_file[file])
44
- [timed.push([file, time]), untimed]
45
- else
46
- [timed, untimed.push(file)]
47
- end
48
- end
31
+ timed_files, untimed_files = timed_and_untimed_files(
32
+ sum_seconds(load_persisted_example_statuses)
33
+ )
34
+
35
+ balance_jobs(
36
+ bucket_count: [files_to_run.size, workers].min,
37
+ timed_files: timed_files,
38
+ untimed_files: untimed_files
39
+ )
40
+ end
41
+
42
+ private
49
43
 
44
+ def balance_jobs(bucket_count:, timed_files:, untimed_files:)
50
45
  balance_by(bucket_count, timed_files, &:last)
51
46
  .map { |bucket| bucket.map(&:first) }
52
47
  .zip(
53
48
  round_robin(bucket_count, untimed_files)
54
49
  ).map(&:flatten)
55
- .map do |files|
56
- Job.new(files, args)
57
- end
50
+ .map { |files| Job.new(files, args) }
58
51
  end
59
52
 
60
- private
53
+ def timed_and_untimed_files(seconds_per_file)
54
+ files_to_run
55
+ .map(&method(:normalize_path))
56
+ .reduce([[], []]) do |(timed, untimed), file|
57
+ if (time = seconds_per_file[file])
58
+ [timed + [[file, time]], untimed]
59
+ else
60
+ [timed, untimed + [file]]
61
+ end
62
+ end
63
+ end
61
64
 
62
65
  def normalize_path(path)
63
66
  ::RSpec::Core::Metadata.relative_path(File.expand_path(path))
@@ -69,22 +72,26 @@ module Flatware
69
72
  )
70
73
  end
71
74
 
72
- def sum_by_example_file
73
- lambda do |times, file_name:, seconds:|
74
- times.merge(file_name => seconds) { |_, old = 0, new| old + new }
75
+ def sum_seconds(statuses)
76
+ statuses.select(&passing)
77
+ .map { |example| parse_example(**example) }
78
+ .reduce({}) do |times, example|
79
+ times.merge(
80
+ example.fetch(:file_name) => example.fetch(:seconds)
81
+ ) do |_, old = 0, new|
82
+ old + new
83
+ end
75
84
  end
76
85
  end
77
86
 
78
87
  def passing
79
- ->(status:, **) { status =~ /pass/i }
88
+ ->(example) { example.fetch(:status) =~ /pass/i }
80
89
  end
81
90
 
82
- def parse_example
83
- lambda do |example_id:, run_time:, **|
84
- seconds = run_time.match(/\d+(\.\d+)?/).to_s.to_f
85
- file_name = ::RSpec::Core::Example.parse_id(example_id).first
86
- { seconds: seconds, file_name: file_name }
87
- end
91
+ def parse_example(example_id:, run_time:, **)
92
+ seconds = run_time.match(/\d+(\.\d+)?/).to_s.to_f
93
+ file_name = ::RSpec::Core::Example.parse_id(example_id).first
94
+ { seconds: seconds, file_name: file_name }
88
95
  end
89
96
 
90
97
  def round_robin(count, items)
@@ -0,0 +1,20 @@
1
+ module Flatware
2
+ module RSpec
3
+ module Marshalable
4
+ require 'flatware/rspec/marshalable/examples_notification'
5
+ require 'flatware/rspec/marshalable/profile_notification'
6
+ require 'flatware/rspec/marshalable/summary_notification'
7
+
8
+ module_function
9
+
10
+ def for_event(event)
11
+ {
12
+ dump_pending: ExamplesNotification,
13
+ dump_failures: ExamplesNotification,
14
+ dump_profile: ProfileNotification,
15
+ dump_summary: SummaryNotification
16
+ }.fetch(event)
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,26 @@
1
+ module Flatware
2
+ module RSpec
3
+ module Marshalable
4
+ ##
5
+ # a subset of the rspec example interface that can traverse drb
6
+ Example = Struct.new(
7
+ *%i[
8
+ execution_result
9
+ full_description
10
+ location
11
+ location_rerun_argument
12
+ ]
13
+ ) do
14
+ def initialize(rspec_example)
15
+ super(*members.map do |attribute|
16
+ rspec_example.public_send(attribute)
17
+ end)
18
+
19
+ @metadata = rspec_example.metadata.slice(:extra_failure_lines, :shared_group_inclusion_backtrace)
20
+ end
21
+
22
+ attr_reader :metadata
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,11 @@
1
+ module Flatware
2
+ module RSpec
3
+ module Marshalable
4
+ ExampleGroup = Struct.new(:location) do
5
+ def initialize(rspec_example_group)
6
+ super(rspec_example_group.location)
7
+ end
8
+ end
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,30 @@
1
+ require 'rspec/core'
2
+ require 'flatware/rspec/marshalable/example'
3
+
4
+ module Flatware
5
+ module RSpec
6
+ module Marshalable
7
+ class ExamplesNotification < ::RSpec::Core::Notifications::ExamplesNotification
8
+ Reporter = Struct.new(:examples, :failed_examples, :pending_examples) do
9
+ def self.from_rspec(reporter)
10
+ new(*members.map { |member| reporter.public_send(member).map(&Example.method(:new)) })
11
+ end
12
+
13
+ def +(other)
14
+ self.class.new(*zip(other).map { |a, b| a + b })
15
+ end
16
+ end
17
+
18
+ attr_reader :reporter
19
+
20
+ def self.from_notification(rspec_notification)
21
+ new Reporter.from_rspec(rspec_notification.instance_variable_get(:@reporter))
22
+ end
23
+
24
+ def +(other)
25
+ self.class.new reporter + other.reporter
26
+ end
27
+ end
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,30 @@
1
+ require 'flatware/rspec/marshalable/example'
2
+ require 'flatware/rspec/marshalable/example_group'
3
+
4
+ module Flatware
5
+ module RSpec
6
+ module Marshalable
7
+ class ProfileNotification < ::RSpec::Core::Notifications::ProfileNotification
8
+ attr_reader :example_groups
9
+
10
+ def +(other)
11
+ self.class.new(
12
+ duration + other.duration,
13
+ examples + other.examples,
14
+ number_of_examples,
15
+ example_groups.merge(other.example_groups)
16
+ )
17
+ end
18
+
19
+ def self.from_notification(rspec_notification)
20
+ new(
21
+ rspec_notification.duration,
22
+ rspec_notification.examples.map(&Example.method(:new)),
23
+ rspec_notification.number_of_examples,
24
+ rspec_notification.instance_variable_get(:@example_groups).transform_keys(&ExampleGroup.method(:new))
25
+ )
26
+ end
27
+ end
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,30 @@
1
+ require 'rspec/core/notifications'
2
+ require 'flatware/rspec/marshalable/example'
3
+
4
+ module Flatware
5
+ module RSpec
6
+ module Marshalable
7
+ class SummaryNotification < ::RSpec::Core::Notifications::SummaryNotification
8
+ def +(other)
9
+ self.class.new(*zip(other).map { |a, b| a + b })
10
+ end
11
+
12
+ def failures?
13
+ [failure_count, errors_outside_of_examples_count].any?(&:positive?)
14
+ end
15
+
16
+ def self.from_notification(summary)
17
+ serialized_examples = [
18
+ summary.examples,
19
+ summary.failed_examples,
20
+ summary.pending_examples
21
+ ].map do |examples|
22
+ examples.map(&Example.method(:new))
23
+ end
24
+
25
+ new(summary.duration, *serialized_examples, *summary.to_a[4..])
26
+ end
27
+ end
28
+ end
29
+ end
30
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: flatware-rspec
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.2.0
4
+ version: 2.0.0.rc1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Brian Dunn
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2019-08-23 00:00:00.000000000 Z
11
+ date: 2021-03-02 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: flatware
@@ -16,14 +16,14 @@ dependencies:
16
16
  requirements:
17
17
  - - '='
18
18
  - !ruby/object:Gem::Version
19
- version: 1.2.0
19
+ version: 2.0.0.rc1
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - '='
25
25
  - !ruby/object:Gem::Version
26
- version: 1.2.0
26
+ version: 2.0.0.rc1
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: rspec
29
29
  requirement: !ruby/object:Gem::Requirement
@@ -52,33 +52,39 @@ files:
52
52
  - lib/flatware/rspec.rb
53
53
  - lib/flatware/rspec/checkpoint.rb
54
54
  - lib/flatware/rspec/cli.rb
55
- - lib/flatware/rspec/example_notification.rb
56
- - lib/flatware/rspec/examples_notification.rb
57
55
  - lib/flatware/rspec/formatter.rb
58
56
  - lib/flatware/rspec/formatters/console.rb
59
57
  - lib/flatware/rspec/job_builder.rb
60
- - lib/flatware/rspec/summary.rb
58
+ - lib/flatware/rspec/marshalable.rb
59
+ - lib/flatware/rspec/marshalable/example.rb
60
+ - lib/flatware/rspec/marshalable/example_group.rb
61
+ - lib/flatware/rspec/marshalable/examples_notification.rb
62
+ - lib/flatware/rspec/marshalable/profile_notification.rb
63
+ - lib/flatware/rspec/marshalable/summary_notification.rb
61
64
  homepage: http://github.com/briandunn/flatware
62
65
  licenses:
63
66
  - MIT
64
67
  metadata: {}
65
- post_install_message:
68
+ post_install_message:
66
69
  rdoc_options: []
67
70
  require_paths:
68
71
  - lib
69
72
  required_ruby_version: !ruby/object:Gem::Requirement
70
73
  requirements:
71
- - - "~>"
74
+ - - ">="
75
+ - !ruby/object:Gem::Version
76
+ version: '2.6'
77
+ - - "<"
72
78
  - !ruby/object:Gem::Version
73
- version: '2.1'
79
+ version: '3.1'
74
80
  required_rubygems_version: !ruby/object:Gem::Requirement
75
81
  requirements:
76
- - - ">="
82
+ - - ">"
77
83
  - !ruby/object:Gem::Version
78
- version: '0'
84
+ version: 1.3.1
79
85
  requirements: []
80
- rubygems_version: 3.0.3
81
- signing_key:
86
+ rubygems_version: 3.2.3
87
+ signing_key:
82
88
  specification_version: 4
83
89
  summary: A distributed rspec runner
84
90
  test_files: []
@@ -1,21 +0,0 @@
1
- require 'rspec/core/formatters/console_codes'
2
-
3
- module Flatware
4
- module RSpec
5
- class ExampleNotification
6
- attr_reader :formatted
7
- def initialize(notification)
8
- @formatted = notification.fully_formatted '!', default_colorizer
9
- end
10
-
11
- def fully_formatted(i, _=nil)
12
- formatted.sub '!', i.to_s
13
- end
14
-
15
- private
16
- def default_colorizer
17
- ::RSpec::Core::Formatters::ConsoleCodes
18
- end
19
- end
20
- end
21
- end
@@ -1,24 +0,0 @@
1
- require 'flatware/rspec/example_notification'
2
- module Flatware
3
- module RSpec
4
- class ExamplesNotification
5
- attr_reader :failure_notifications
6
-
7
- def initialize(failure_notifications)
8
- @failure_notifications = failure_notifications.map(&ExampleNotification.method(:new))
9
- end
10
-
11
- def +(other)
12
- self.class.new failure_notifications + other.failure_notifications
13
- end
14
-
15
- def fully_formatted_failed_examples(*)
16
- formatted = "\n\nFailures:\n"
17
- failure_notifications.each_with_index do |failure, index|
18
- formatted << failure.fully_formatted(index.next)
19
- end
20
- formatted
21
- end
22
- end
23
- end
24
- end
@@ -1,26 +0,0 @@
1
- require 'rspec/core/notifications'
2
- module Flatware
3
- module RSpec
4
- class Example
5
- attr_reader :location_rerun_argument, :full_description
6
- def initialize(rspec_example)
7
- @full_description = rspec_example.full_description
8
- @location_rerun_argument = rspec_example.location_rerun_argument
9
- end
10
- end
11
-
12
- class Summary < ::RSpec::Core::Notifications::SummaryNotification
13
- def +(other)
14
- self.class.new(*zip(other).map {|a,b| a + b})
15
- end
16
-
17
- def self.from_notification(summary)
18
- serialized_examples = [summary.examples, summary.failed_examples, summary.pending_examples].map do |examples|
19
- examples.map(&Example.method(:new))
20
- end
21
-
22
- new summary.duration, *serialized_examples, *summary.to_a[4..-1]
23
- end
24
- end
25
- end
26
- end