specwrk 0.14.0 → 0.15.0

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 7890636149b3658e663cfc5957522e9147f0ede2a6ff4e28c27b6966c1b45b40
4
- data.tar.gz: a76c0bd696a11d4b1703dabd156466611678bcec30b35fd6994ced48444e9dcf
3
+ metadata.gz: 63eedb1506644bd71c457579fb2de19779c66c565b2c614284272152506648ca
4
+ data.tar.gz: eb5c83efcd7a9d76623867ec42d48a335e2f349c6608326abba643252a31e486
5
5
  SHA512:
6
- metadata.gz: 9ad2c96e0111c5b523836f22a3eda9133f7ef838b5239c8355118a299c9ac6ea523bdb524955bf7b66caffea1397d5470cfd3554e877247268fce332ba34ac43
7
- data.tar.gz: dec3475151008f2e4452ed4f5e96c413d63d61c4b2ebe38d315a3d795bed58247341c53c60b8dd7f15385860a1d381d77f60cdba61ce5738c24fb0f27a50b72f
6
+ metadata.gz: 8235b7ddcd7bbee6acc73ec3c53bf8bd9987d769babc42159248b514f326b381ad49a4247e12c649d21d700d158c7f1b83b1b5c93ff6200eb38f8e41b46f4df1
7
+ data.tar.gz: f98b5df6bb5a72bd515c5324c17c8c76daf1a08c876fc6d4ab8b7a9f9f6a6477248b34dc9a82c73f289f417a8026bd7b2cc6eb367c25948d17c5f0c5d918844d
data/.circleci/config.yml CHANGED
@@ -83,6 +83,17 @@ jobs:
83
83
  - .specwrk/report.json
84
84
  key: specwrk-{{ .Branch }}
85
85
  ## /SPECWRK STEP ##
86
+
87
+ - run:
88
+ name: Echo the workers output for giggles
89
+ command: |
90
+ shopt -s nullglob
91
+ for file in /tmp/specwrk/main/*.ndjson; do
92
+ echo "===== $file ====="
93
+ cat "$file"
94
+ echo
95
+ done
96
+
86
97
 
87
98
  specwrk-multi-node-prepare:
88
99
  docker:
@@ -116,7 +127,6 @@ jobs:
116
127
  --key "$SPECWRK_KEY" \
117
128
  --run "$CIRCLE_WORKFLOW_ID" \
118
129
  spec/
119
-
120
130
  ## /SPECWRK STEP ##
121
131
 
122
132
  specwrk-multi-node:
@@ -154,3 +164,14 @@ jobs:
154
164
  --run "$CIRCLE_WORKFLOW_ID" \
155
165
  --count 2
156
166
  ## /SPECWRK STEP ##
167
+
168
+ - run:
169
+ name: Echo the workers output for giggles
170
+ command: |
171
+ shopt -s nullglob
172
+ for file in /tmp/specwrk/main/*.ndjson; do
173
+ echo "===== $file ====="
174
+ cat "$file"
175
+ echo
176
+ done
177
+
data/lib/specwrk/cli.rb CHANGED
@@ -132,7 +132,7 @@ module Specwrk
132
132
  examples = ListExamples.new(dir).examples
133
133
 
134
134
  Client.wait_for_server!
135
- Client.new.seed(examples, max_retries: max_retries)
135
+ Client.new.seed(examples, max_retries)
136
136
  file_count = examples.group_by { |e| e[:file_path] }.keys.size
137
137
  puts "🌱 Seeded #{examples.size} examples across #{file_count} files"
138
138
  rescue Errno::ECONNREFUSED
@@ -19,10 +19,25 @@ module Specwrk
19
19
  puts "\nFinished in #{Specwrk.human_readable_duration total_duration} " \
20
20
  "(total execution time of #{Specwrk.human_readable_duration total_run_time})\n"
21
21
 
22
+ if flake_count.positive?
23
+ puts "\nFlaked examples:\n\n"
24
+ flake_reruns_lines.each { |(command, description)| print "#{colorizer.wrap(command, :magenta)} #{colorizer.wrap(description, :cyan)}\n" }
25
+ puts ""
26
+ end
27
+
22
28
  client.shutdown
23
29
 
24
30
  if failure_count.positive?
25
31
  puts colorizer.wrap(totals_line, :red)
32
+
33
+ puts "\nFailed examples:\n\n"
34
+ failure_reruns_lines.each { |(command, description)| print "#{colorizer.wrap(command, :red)} #{colorizer.wrap(description, :cyan)}\n" }
35
+ puts ""
36
+
37
+ 1
38
+ elsif unexecuted_count.positive?
39
+ puts colorizer.wrap(totals_line, :red)
40
+
26
41
  1
27
42
  elsif pending_count.positive?
28
43
  puts colorizer.wrap(totals_line, :yellow)
@@ -44,11 +59,29 @@ module Specwrk
44
59
  def totals_line
45
60
  summary = RSpec::Core::Formatters::Helpers.pluralize(example_count, "example") +
46
61
  ", " + RSpec::Core::Formatters::Helpers.pluralize(failure_count, "failure")
47
- summary += ", #{pending_count} pending" if pending_count > 0
62
+ summary += ", #{pending_count} pending" if pending_count.positive?
63
+ summary += ", #{RSpec::Core::Formatters::Helpers.pluralize(flake_count, "example")} flaked #{RSpec::Core::Formatters::Helpers.pluralize(total_flakes, "time")}" if flake_count.positive?
64
+ summary += ". #{RSpec::Core::Formatters::Helpers.pluralize(unexecuted_count, "example")} not executed" if unexecuted_count.positive?
48
65
 
49
66
  summary
50
67
  end
51
68
 
69
+ def failure_reruns_lines
70
+ @failure_reruns_lines ||= report_data.dig(:examples).values.map do |example|
71
+ next unless example[:status] == "failed"
72
+
73
+ ["rspec #{example[:file_path]}:#{example[:line_number]}", "# #{example[:full_description]}"]
74
+ end.compact
75
+ end
76
+
77
+ def flake_reruns_lines
78
+ @flake_reruns_lines ||= report_data.dig(:flakes).map do |example_id, count|
79
+ example = report_data.dig(:examples, example_id)
80
+
81
+ ["rspec #{example[:file_path]}:#{example[:line_number]}", "# #{example[:full_description]}. Failed #{RSpec::Core::Formatters::Helpers.pluralize(count, "time")} before passing."]
82
+ end.compact
83
+ end
84
+
52
85
  def report_data
53
86
  @report_data ||= client.report
54
87
  end
@@ -69,10 +102,22 @@ module Specwrk
69
102
  report_data.dig(:meta, :pending)
70
103
  end
71
104
 
105
+ def unexecuted_count
106
+ report_data.dig(:meta, :unexecuted)
107
+ end
108
+
72
109
  def example_count
73
110
  report_data.dig(:examples).length
74
111
  end
75
112
 
113
+ def flake_count
114
+ report_data.dig(:flakes).length
115
+ end
116
+
117
+ def total_flakes
118
+ @total_flakes ||= report_data.dig(:flakes).values.sum
119
+ end
120
+
76
121
  def client
77
122
  @client ||= Client.new
78
123
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Specwrk
4
- VERSION = "0.14.0"
4
+ VERSION = "0.15.0"
5
5
  end
@@ -145,6 +145,7 @@ module Specwrk
145
145
 
146
146
  def with_response
147
147
  pending.clear
148
+ processing.clear
148
149
  failure_counts.clear
149
150
 
150
151
  pending.max_retries = payload.fetch(:max_retries, "0").to_i
@@ -331,15 +332,16 @@ module Specwrk
331
332
 
332
333
  class Report < Base
333
334
  def with_response
334
- [200, {"content-type" => "application/json"}, [JSON.generate(completed.dump)]]
335
+ completed_dump = completed.dump
336
+ completed_dump[:meta][:unexecuted] = pending.length + processing.length
337
+ completed_dump[:flakes] = failure_counts.to_h.reject { |id, _count| completed_dump.dig(:examples, id, :status) == "failed" }
338
+
339
+ [200, {"content-type" => "application/json"}, [JSON.generate(completed_dump)]]
335
340
  end
336
341
  end
337
342
 
338
343
  class Shutdown < Base
339
344
  def with_response
340
- pending.clear
341
- processing.clear
342
-
343
345
  interupt! if ENV["SPECWRK_SRV_SINGLE_RUN"]
344
346
 
345
347
  [200, {"content-type" => "text/plain"}, ["✌️"]]
@@ -13,7 +13,7 @@ module Specwrk
13
13
 
14
14
  def stop(group_notification)
15
15
  group_notification.notifications.map do |notification|
16
- examples << {
16
+ hash = {
17
17
  id: notification.example.id,
18
18
  full_description: notification.example.full_description,
19
19
  status: notification.example.execution_result.status,
@@ -23,6 +23,16 @@ module Specwrk
23
23
  finished_at: notification.example.execution_result.finished_at.iso8601(6),
24
24
  run_time: notification.example.execution_result.run_time
25
25
  }
26
+
27
+ if (e = notification.example.exception)
28
+ hash[:exception] = {
29
+ class: e.class.name,
30
+ message: e.message,
31
+ backtrace: notification.formatted_backtrace
32
+ }
33
+ end
34
+
35
+ examples << hash
26
36
  end
27
37
  end
28
38
  end
@@ -24,12 +24,13 @@ module Specwrk
24
24
 
25
25
  example_ids = examples.map { |example| example[:id] }
26
26
 
27
- options = RSpec::Core::ConfigurationOptions.new rspec_options + example_ids
27
+ options = RSpec::Core::ConfigurationOptions.new ["--format", "Specwrk::Worker::NullFormatter"] + example_ids
28
28
  RSpec::Core::Runner.new(options).run($stderr, $stdout)
29
29
  end
30
30
 
31
31
  # https://github.com/skroutz/rspecq/blob/341383ce3ca25f42fad5483cbb6a00ba1c405570/lib/rspecq/worker.rb#L208-L224
32
32
  def reset!
33
+ flush_log
33
34
  completion_formatter.examples.clear
34
35
 
35
36
  RSpec.clear_examples
@@ -71,13 +72,25 @@ module Specwrk
71
72
  @completion_formatter ||= CompletionFormatter.new
72
73
  end
73
74
 
74
- def rspec_options
75
- @rspec_options ||= if ENV["SPECWRK_OUT"]
76
- ["--format", "json", "--out", File.join(ENV["SPECWRK_OUT"], "#{ENV.fetch("SPECWRK_ID", "specwrk-worker")}.json")]
75
+ def flush_log
76
+ completion_formatter.examples.each { |example| json_log_file.puts example }
77
+ end
78
+
79
+ def json_log_file
80
+ @json_log_file ||= if json_log_file_path
81
+ FileUtils.mkdir_p(File.dirname(json_log_file_path))
82
+ File.truncate(json_log_file_path, 0) if File.exist?(json_log_file_path)
83
+ File.open(json_log_file_path, "a", sync: true)
77
84
  else
78
- ["--format", "Specwrk::Worker::NullFormatter"]
85
+ File.open(File::NULL, "a")
79
86
  end
80
87
  end
88
+
89
+ def json_log_file_path
90
+ return unless ENV["SPECWRK_OUT"]
91
+
92
+ @json_log_file_path ||= File.join(ENV["SPECWRK_OUT"], ENV["SPECWRK_RUN"], "#{ENV["SPECWRK_FORKED"]}.ndjson")
93
+ end
81
94
  end
82
95
  end
83
96
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: specwrk
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.14.0
4
+ version: 0.15.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Daniel Westendorf