flatware 0.3.2 → 0.4.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +83 -39
- data/lib/flatware-cucumber.rb +1 -0
- data/lib/flatware-rspec.rb +1 -0
- data/lib/flatware.rb +2 -10
- data/lib/flatware/broadcaster.rb +15 -0
- data/lib/flatware/cli.rb +10 -34
- data/lib/flatware/cucumber.rb +37 -12
- data/lib/flatware/cucumber/checkpoint.rb +28 -0
- data/lib/flatware/cucumber/cli.rb +22 -0
- data/lib/flatware/cucumber/formatter.rb +36 -84
- data/lib/flatware/{formatters/cucumber → cucumber/formatters}/console.rb +5 -3
- data/lib/flatware/{formatters/cucumber → cucumber/formatters}/console/summary.rb +3 -3
- data/lib/flatware/cucumber/result.rb +27 -0
- data/lib/flatware/cucumber/scenario_result.rb +38 -0
- data/lib/flatware/cucumber/step_result.rb +30 -0
- data/lib/flatware/poller.rb +2 -2
- data/lib/flatware/rspec.rb +28 -0
- data/lib/flatware/rspec/checkpoint.rb +29 -0
- data/lib/flatware/rspec/cli.rb +16 -0
- data/lib/flatware/rspec/example_notification.rb +21 -0
- data/lib/flatware/rspec/examples_notification.rb +24 -0
- data/lib/flatware/rspec/formatter.rb +50 -0
- data/lib/flatware/rspec/formatters/console.rb +33 -0
- data/lib/flatware/rspec/summary.rb +40 -0
- data/lib/flatware/serialized_exception.rb +12 -8
- data/lib/flatware/sink.rb +43 -33
- data/lib/flatware/socket.rb +89 -25
- data/lib/flatware/version.rb +1 -1
- data/lib/flatware/worker.rb +16 -9
- metadata +27 -55
- data/lib/flatware/checkpoint.rb +0 -28
- data/lib/flatware/checkpoint_handler.rb +0 -45
- data/lib/flatware/dispatcher.rb +0 -31
- data/lib/flatware/fireable.rb +0 -34
- data/lib/flatware/formatters.rb +0 -27
- data/lib/flatware/formatters/cucumber/http.rb +0 -83
- data/lib/flatware/result.rb +0 -25
- data/lib/flatware/scenario_decorator.rb +0 -22
- data/lib/flatware/scenario_result.rb +0 -36
- data/lib/flatware/step_result.rb +0 -27
@@ -1,113 +1,65 @@
|
|
1
|
-
require '
|
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
|
-
|
10
|
-
|
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
|
-
|
35
|
-
|
36
|
-
|
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
|
-
|
46
|
-
|
47
|
-
|
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
|
54
|
-
|
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
|
-
|
58
|
-
@in_a_step = ! @in_examples
|
59
|
-
end
|
31
|
+
private
|
60
32
|
|
61
|
-
def
|
62
|
-
|
33
|
+
def reset
|
34
|
+
@steps = []
|
35
|
+
@scenarios = []
|
36
|
+
@matched_steps = Set.new
|
63
37
|
end
|
64
38
|
|
65
|
-
|
66
|
-
@in_a_step = true
|
67
|
-
end
|
39
|
+
attr_reader :steps, :scenarios, :matched_steps
|
68
40
|
|
69
|
-
def
|
70
|
-
|
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
|
74
|
-
|
45
|
+
def on_step_match(event)
|
46
|
+
@matched_steps << event.step_match.location.to_s
|
75
47
|
end
|
76
48
|
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
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
|
85
|
-
Sink::client.
|
56
|
+
def on_finished_testing(*)
|
57
|
+
Sink::client.checkpoint Checkpoint.new steps, scenarios
|
58
|
+
reset
|
86
59
|
end
|
87
60
|
|
88
|
-
|
89
|
-
|
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/
|
1
|
+
require 'flatware/cucumber/formatters/console/summary'
|
2
2
|
require 'cucumber/formatter/console'
|
3
3
|
|
4
|
-
module Flatware::Formatters
|
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(
|
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/
|
3
|
-
require 'flatware/checkpoint'
|
2
|
+
require 'flatware/cucumber/formatters/console'
|
3
|
+
require 'flatware/cucumber/checkpoint'
|
4
4
|
|
5
|
-
module Flatware::Formatters
|
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
|
data/lib/flatware/poller.rb
CHANGED
@@ -21,14 +21,14 @@ module Flatware
|
|
21
21
|
def find_wrapped_socket
|
22
22
|
->(s) do
|
23
23
|
sockets.find do |socket|
|
24
|
-
socket.
|
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.
|
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
|