flatware 0.3.2 → 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (41) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +83 -39
  3. data/lib/flatware-cucumber.rb +1 -0
  4. data/lib/flatware-rspec.rb +1 -0
  5. data/lib/flatware.rb +2 -10
  6. data/lib/flatware/broadcaster.rb +15 -0
  7. data/lib/flatware/cli.rb +10 -34
  8. data/lib/flatware/cucumber.rb +37 -12
  9. data/lib/flatware/cucumber/checkpoint.rb +28 -0
  10. data/lib/flatware/cucumber/cli.rb +22 -0
  11. data/lib/flatware/cucumber/formatter.rb +36 -84
  12. data/lib/flatware/{formatters/cucumber → cucumber/formatters}/console.rb +5 -3
  13. data/lib/flatware/{formatters/cucumber → cucumber/formatters}/console/summary.rb +3 -3
  14. data/lib/flatware/cucumber/result.rb +27 -0
  15. data/lib/flatware/cucumber/scenario_result.rb +38 -0
  16. data/lib/flatware/cucumber/step_result.rb +30 -0
  17. data/lib/flatware/poller.rb +2 -2
  18. data/lib/flatware/rspec.rb +28 -0
  19. data/lib/flatware/rspec/checkpoint.rb +29 -0
  20. data/lib/flatware/rspec/cli.rb +16 -0
  21. data/lib/flatware/rspec/example_notification.rb +21 -0
  22. data/lib/flatware/rspec/examples_notification.rb +24 -0
  23. data/lib/flatware/rspec/formatter.rb +50 -0
  24. data/lib/flatware/rspec/formatters/console.rb +33 -0
  25. data/lib/flatware/rspec/summary.rb +40 -0
  26. data/lib/flatware/serialized_exception.rb +12 -8
  27. data/lib/flatware/sink.rb +43 -33
  28. data/lib/flatware/socket.rb +89 -25
  29. data/lib/flatware/version.rb +1 -1
  30. data/lib/flatware/worker.rb +16 -9
  31. metadata +27 -55
  32. data/lib/flatware/checkpoint.rb +0 -28
  33. data/lib/flatware/checkpoint_handler.rb +0 -45
  34. data/lib/flatware/dispatcher.rb +0 -31
  35. data/lib/flatware/fireable.rb +0 -34
  36. data/lib/flatware/formatters.rb +0 -27
  37. data/lib/flatware/formatters/cucumber/http.rb +0 -83
  38. data/lib/flatware/result.rb +0 -25
  39. data/lib/flatware/scenario_decorator.rb +0 -22
  40. data/lib/flatware/scenario_result.rb +0 -36
  41. data/lib/flatware/step_result.rb +0 -27
@@ -1,113 +1,65 @@
1
- require 'flatware/checkpoint'
2
- require 'flatware/scenario_decorator'
1
+ require 'cucumber'
3
2
  require 'flatware/sink'
4
3
  require 'ostruct'
5
4
  module Flatware
6
5
  module Cucumber
7
6
  class Formatter
8
-
9
- def initialize(step_mother, *)
10
- @collector = Collector.new step_mother
11
- @scenarios = []
12
- @in_a_step = false
13
- end
14
-
15
- def after_features(*)
16
- checkpoint = collector.checkpoint
17
- scenarios.select(&:exception).map(&:file_colon_line).each do |file_colon_line|
18
- scenario = checkpoint.scenarios.detect do |scenario|
19
- scenario.file_colon_line == file_colon_line
20
- end
21
- scenario.failed_outside_step!(file_colon_line) if scenario
7
+ Checkpoint = Struct.new :steps, :scenarios do
8
+ def failures?
9
+ scenarios.any? &:failed?
22
10
  end
23
- Sink::client.checkpoint checkpoint
24
- end
25
-
26
- def after_step_result(_, _, _, status, *)
27
- send_progress(status)
28
- end
29
-
30
- def table_cell_value(_, status)
31
- send_progress(status) if status
32
11
  end
33
12
 
34
- def exception(exception, status)
35
- unless @in_a_step
36
- current_scenario.exception = exception
37
- send_progress(status)
13
+ Scenario = Struct.new :name, :file_colon_line, :status do
14
+ def failed?
15
+ status == :failed
38
16
  end
39
- end
40
-
41
- def respond_to?(x)
42
- super
43
- end
44
17
 
45
- def before_outline_table(*)
46
- @in_examples = true
47
- end
48
-
49
- def after_outline_table(*)
50
- @in_examples = false
18
+ def failed_outside_step?
19
+ false
20
+ end
51
21
  end
52
22
 
53
- def before_table_cell(*)
54
- @in_a_step = @in_examples
23
+ def initialize(config)
24
+ config.on_event :after_test_case, &method(:on_after_test_case)
25
+ config.on_event :after_test_step, &method(:on_after_test_step)
26
+ config.on_event :finished_testing, &method(:on_finished_testing)
27
+ config.on_event :step_match, &method(:on_step_match)
28
+ reset
55
29
  end
56
30
 
57
- def after_table_cell(*)
58
- @in_a_step = ! @in_examples
59
- end
31
+ private
60
32
 
61
- def after_table_row(table_row)
62
- exception(table_row.exception, :failed) if table_row.exception
33
+ def reset
34
+ @steps = []
35
+ @scenarios = []
36
+ @matched_steps = Set.new
63
37
  end
64
38
 
65
- def before_step(*)
66
- @in_a_step = true
67
- end
39
+ attr_reader :steps, :scenarios, :matched_steps
68
40
 
69
- def after_step(*)
70
- @in_a_step = false
41
+ def on_after_test_case(event)
42
+ scenarios << Scenario.new(event.test_case.name, event.test_case.location.to_s, event.result.to_sym)
71
43
  end
72
44
 
73
- def scenario_name(_, name, file_colon_line, *)
74
- scenarios.push OpenStruct.new file_colon_line: file_colon_line, name: name
45
+ def on_step_match(event)
46
+ @matched_steps << event.step_match.location.to_s
75
47
  end
76
48
 
77
- private
78
- attr_reader :collector, :scenarios
79
-
80
- def current_scenario
81
- scenarios.last
49
+ def on_after_test_step(event)
50
+ if really_a_step?(event.test_step) or event.result.undefined?
51
+ steps << StepResult.new(event.result.to_sym, event.result.failed? && event.result.exception)
52
+ Sink::client.progress Result.new event.result.to_sym
53
+ end
82
54
  end
83
55
 
84
- def send_progress(status)
85
- Sink::client.progress Result.new status
56
+ def on_finished_testing(*)
57
+ Sink::client.checkpoint Checkpoint.new steps, scenarios
58
+ reset
86
59
  end
87
60
 
88
- class Collector
89
- attr_reader :step_mother
90
- def initialize(step_mother)
91
- @step_mother = step_mother
92
- snapshot
93
- end
94
-
95
- def checkpoint
96
- Checkpoint.new(step_mother.steps - @ran_steps, decorate_scenarios(step_mother.scenarios - @ran_scenarios)).tap do
97
- snapshot
98
- end
99
- end
100
-
101
- private
102
-
103
- def snapshot
104
- @ran_steps = step_mother.steps.dup
105
- @ran_scenarios = step_mother.scenarios.dup
106
- end
107
-
108
- def decorate_scenarios(scenarios)
109
- scenarios.map { |scenario| ScenarioDecorator.new(scenario) }
110
- end
61
+ def really_a_step?(step)
62
+ matched_steps.include?(step.action_location.to_s)
111
63
  end
112
64
  end
113
65
  end
@@ -1,7 +1,7 @@
1
- require 'flatware/formatters/cucumber/console/summary'
1
+ require 'flatware/cucumber/formatters/console/summary'
2
2
  require 'cucumber/formatter/console'
3
3
 
4
- module Flatware::Formatters::Cucumber
4
+ module Flatware::Cucumber::Formatters
5
5
  class Console
6
6
  #for format_string
7
7
  include ::Cucumber::Formatter::Console
@@ -26,7 +26,9 @@ module Flatware::Formatters::Cucumber
26
26
  out.print format result.progress
27
27
  end
28
28
 
29
- def summarize(steps, scenarios)
29
+ def summarize(checkpoints)
30
+ steps = checkpoints.flat_map(&:steps)
31
+ scenarios = checkpoints.flat_map(&:scenarios)
30
32
  Summary.new(steps, scenarios, out).summarize
31
33
  end
32
34
 
@@ -1,8 +1,8 @@
1
1
  require 'cucumber/formatter/console'
2
- require 'flatware/formatters/cucumber/console'
3
- require 'flatware/checkpoint'
2
+ require 'flatware/cucumber/formatters/console'
3
+ require 'flatware/cucumber/checkpoint'
4
4
 
5
- module Flatware::Formatters::Cucumber
5
+ module Flatware::Cucumber::Formatters
6
6
  class Console
7
7
  class Summary
8
8
  include ::Cucumber::Formatter::Console
@@ -0,0 +1,27 @@
1
+ module Flatware
2
+ module Cucumber
3
+ class Result
4
+ attr_reader :progress, :worker
5
+
6
+ def initialize(progress)
7
+ @progress = progress
8
+ @worker = ENV['TEST_ENV_NUMBER'].to_i
9
+ end
10
+
11
+ class << self
12
+ def step(*args)
13
+ step = StepResult.new *args
14
+ new step.progress, [step]
15
+ end
16
+
17
+ def status(status)
18
+ new status
19
+ end
20
+
21
+ def background(status, exception)
22
+ new '', [StepResult.new(status, exception)]
23
+ end
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,38 @@
1
+ require 'flatware/serialized_exception'
2
+ module Flatware
3
+ module Cucumber
4
+ class ScenarioResult
5
+ attr_reader :status, :file_colon_line, :name
6
+ def initialize(status, file_colon_line, name, e)
7
+ @status = status
8
+ @file_colon_line = file_colon_line
9
+ @name = name
10
+ @exception = SerializedException.new(e.class, e.message, e.backtrace) if e
11
+ @failed_outside_step = false
12
+ end
13
+
14
+ def passed?
15
+ status == :passed
16
+ end
17
+
18
+ def failed?
19
+ status == :failed
20
+ end
21
+
22
+ def failed_outside_step!(file_colon_line)
23
+ @failed_outside_step = file_colon_line
24
+ end
25
+
26
+ def failed_outside_step?
27
+ !!@failed_outside_step
28
+ end
29
+
30
+ def exception
31
+ @exception.tap do |e|
32
+ e.backtrace = e.backtrace.grep(Regexp.new(Dir.pwd)).map { |line| line[Dir.pwd.size..-1] }
33
+ e.backtrace = e.backtrace + [@failed_outside_step] if failed_outside_step?
34
+ end
35
+ end
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,30 @@
1
+ require 'flatware/serialized_exception'
2
+ module Flatware
3
+ module Cucumber
4
+ class StepResult
5
+ attr_reader :status, :exception
6
+
7
+ def initialize(status, exception)
8
+ @status, @exception = status, (serialized(exception) if exception)
9
+ end
10
+
11
+ def passed?
12
+ status == :passed
13
+ end
14
+
15
+ def failed?
16
+ status == :failed
17
+ end
18
+
19
+ def progress
20
+ Cucumber::ProgressString.format(status)
21
+ end
22
+
23
+ private
24
+ def serialized(e)
25
+ e.backtrace and e.backtrace.unshift e.backtrace.shift.sub(Dir.pwd, '.')
26
+ SerializedException.new(e.class, e.message, e.backtrace)
27
+ end
28
+ end
29
+ end
30
+ end
@@ -21,14 +21,14 @@ module Flatware
21
21
  def find_wrapped_socket
22
22
  ->(s) do
23
23
  sockets.find do |socket|
24
- socket.s == s
24
+ socket.socket == s
25
25
  end
26
26
  end
27
27
  end
28
28
 
29
29
  def register_sockets
30
30
  sockets.each do |socket|
31
- zmq_poller.register_readable socket.s
31
+ zmq_poller.register_readable socket.socket
32
32
  end
33
33
  end
34
34
  end
@@ -0,0 +1,28 @@
1
+ require 'rspec/core'
2
+ require 'rspec/expectations'
3
+ require 'flatware/rspec/cli'
4
+
5
+ module Flatware
6
+ module RSpec
7
+ require 'flatware/rspec/formatters/console'
8
+ require 'flatware/rspec/formatter'
9
+
10
+ def self.extract_jobs_from_args(args, workers:)
11
+
12
+ options = ::RSpec::Core::ConfigurationOptions.new(args)
13
+ configuration = ::RSpec::Core::Configuration.new
14
+ def configuration.command() 'rspec' end
15
+ options.configure(configuration)
16
+ configuration.files_to_run.uniq.map do |file|
17
+ Job.new(file, args)
18
+ end
19
+ end
20
+
21
+ def self.run(job, options={})
22
+ runner = ::RSpec::Core::Runner
23
+ def runner.trap_interrupt() end
24
+
25
+ runner.run(%w[--format Flatware::RSpec::Formatter] + Array(job), $stderr, $stdout)
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,29 @@
1
+ require 'flatware/rspec/examples_notification'
2
+
3
+ module Flatware
4
+ module RSpec
5
+ class Checkpoint
6
+ attr_reader :summary, :failures_notification
7
+
8
+ def initialize(summary, failures_notification)
9
+ @summary, @failures_notification = summary, ExamplesNotification.new(failures_notification.failure_notifications)
10
+ end
11
+
12
+ def +(other)
13
+ self.class.new summary + other.summary, failures_notification + other.failures_notification
14
+ end
15
+
16
+ def failures?
17
+ summary.failure_count > 0
18
+ end
19
+
20
+ def failure_notifications
21
+ failures_notification.failure_notifications
22
+ end
23
+
24
+ def fully_formatted_failed_examples(*args)
25
+ failures_notification.fully_formatted_failed_examples(*args)
26
+ end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,16 @@
1
+ require 'flatware/cli'
2
+
3
+ module Flatware
4
+ class CLI
5
+ 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"
9
+ def rspec(*rspec_args)
10
+ jobs = RSpec.extract_jobs_from_args rspec_args, workers: workers
11
+ 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)
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,21 @@
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
@@ -0,0 +1,24 @@
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
@@ -0,0 +1,50 @@
1
+ require 'flatware/rspec/checkpoint'
2
+ require 'flatware/rspec/summary'
3
+ require 'rspec/core/formatters/console_codes'
4
+
5
+ module Flatware
6
+ module RSpec
7
+ ProgressMessage = Struct.new(:progress)
8
+
9
+ class Formatter
10
+ attr_reader :summary, :output
11
+
12
+ def initialize(stdout)
13
+ @output = stdout
14
+ end
15
+
16
+ def example_passed(example)
17
+ send_progress :passed
18
+ end
19
+
20
+ def example_failed(example)
21
+ send_progress :failed
22
+ end
23
+
24
+ def example_pending(example)
25
+ send_progress :pending
26
+ end
27
+
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
34
+ end
35
+
36
+ def close(*)
37
+ Sink::client.checkpoint Checkpoint.new(summary, @failure_notification)
38
+ @failure_notification = nil
39
+ end
40
+
41
+ private
42
+
43
+ def send_progress(status)
44
+ Sink::client.progress ProgressMessage.new status
45
+ end
46
+ end
47
+
48
+ ::RSpec::Core::Formatters.register Formatter, :example_passed, :example_failed, :example_pending, :dump_summary, :dump_failures, :close
49
+ end
50
+ end