rspec-activerecord-formatter 1.3.0 → 2.0.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 +5 -5
- data/README.md +8 -3
- data/lib/rspec-activerecord-formatter.rb +5 -0
- data/lib/rspec/activerecord/base.rb +43 -0
- data/lib/rspec/activerecord/documentation_formatter.rb +58 -0
- data/lib/rspec/activerecord/formatter.rb +1 -107
- data/lib/rspec/activerecord/helpers/report.rb +44 -0
- data/lib/rspec/activerecord/progress_formatter.rb +44 -0
- data/rspec-activerecord-formatter.gemspec +1 -1
- metadata +7 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 796768aef6b284e761135f02bf4fde2991c6542905abd5084fc77e3fb8005f2b
|
4
|
+
data.tar.gz: 459eab6e0f667b0c683d465a335d9f6f21ee3976d75440fc1c53a4c75c04e0f0
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: fe56977ad258d136496454cdca232bb1516dd8e265fd6b5e3239ca6bba9b34286b3785a47e4bb8e42272cf1ed9fc69d4bc760b44c3e28ec0a8daeef16086e3ba
|
7
|
+
data.tar.gz: bd6ed8ff7fa849d319d2e1bccfd9893fa7f6e647c71224279242849788bdaef46e1567ae002cbe43a468d7292cd11338d2713422b22fd9550d4e407b7441bc8b
|
data/README.md
CHANGED
@@ -27,14 +27,14 @@ The current answer is to change your `.rspec` initializer to include the followi
|
|
27
27
|
|
28
28
|
--require rspec-activerecord-formatter
|
29
29
|
--require rails_helper
|
30
|
-
--format
|
30
|
+
--format ActiveRecordDocumentationFormatter
|
31
31
|
|
32
32
|
We have to include the rails_helper so that ActiveRecord is loaded prior to trying to load the
|
33
33
|
formatter. That way, we can hook into AR creations.
|
34
34
|
|
35
35
|
You can also run the formatter as a one-off option to rspec:
|
36
36
|
|
37
|
-
rspec path/to/example_spec.rb --require rspec-activerecord-formatter --require rails_helper --format
|
37
|
+
rspec path/to/example_spec.rb --require rspec-activerecord-formatter --require rails_helper --format ActiveRecordDocumentationFormatter
|
38
38
|
|
39
39
|
Once you set the formatter, you should now see the number of objects created and total queries
|
40
40
|
for each of your tests:
|
@@ -45,12 +45,17 @@ You'll also get a summary at the end of your test run:
|
|
45
45
|
|
46
46
|

|
47
47
|
|
48
|
+
If you want less granularity, you can also use the progress formatter:
|
49
|
+
|
50
|
+
--require rspec-activerecord-formatter
|
51
|
+
--require rails_helper
|
52
|
+
--format ActiveRecordProgressFormatter
|
53
|
+
|
48
54
|
Next Steps
|
49
55
|
------------
|
50
56
|
* The method I was using to count AR objects doesn't work well with DatabaseCleaner when not explicitly wiring the library into `before` blocks.
|
51
57
|
I'd like to be able to go back to a method other than scanning for `INSERT INTO` strings.
|
52
58
|
* Configuration, especially formatting the output to optionally outdent the counts.
|
53
|
-
* Add a `--profile`-like behavior to output the most offending tests.
|
54
59
|
* The current dependency versions are a vague guess. They can and should clearly be more lenient.
|
55
60
|
* I dunno, tests.
|
56
61
|
|
@@ -1 +1,6 @@
|
|
1
|
+
require "rspec/activerecord/helpers/collector"
|
2
|
+
require "rspec/activerecord/helpers/report"
|
3
|
+
require 'rspec/activerecord/base'
|
4
|
+
require 'rspec/activerecord/progress_formatter'
|
5
|
+
require 'rspec/activerecord/documentation_formatter'
|
1
6
|
require 'rspec/activerecord/formatter'
|
@@ -0,0 +1,43 @@
|
|
1
|
+
class ActiveRecordFormatterBase
|
2
|
+
attr_reader :colorizer, :summary, :collector
|
3
|
+
|
4
|
+
def initialize(summary, collector)
|
5
|
+
@colorizer = ::RSpec::Core::Formatters::ConsoleCodes
|
6
|
+
@summary = summary
|
7
|
+
@collector = collector
|
8
|
+
end
|
9
|
+
|
10
|
+
def colorized_summary
|
11
|
+
formatted = "\nFinished in #{summary.formatted_duration} " \
|
12
|
+
"(files took #{summary.formatted_load_time} to load)\n" \
|
13
|
+
"#{colorized_expanded_totals}\n"
|
14
|
+
|
15
|
+
unless summary.failed_examples.empty?
|
16
|
+
formatted << summary.colorized_rerun_commands(colorizer) << "\n"
|
17
|
+
end
|
18
|
+
|
19
|
+
formatted
|
20
|
+
end
|
21
|
+
|
22
|
+
private
|
23
|
+
|
24
|
+
def colorized_expanded_totals
|
25
|
+
if summary.failure_count > 0
|
26
|
+
colorizer.wrap(expanded_totals_line, RSpec.configuration.failure_color)
|
27
|
+
elsif summary.pending_count > 0
|
28
|
+
colorizer.wrap(expanded_totals_line, RSpec.configuration.pending_color)
|
29
|
+
else
|
30
|
+
colorizer.wrap(expanded_totals_line, RSpec.configuration.success_color)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
def expanded_totals_line
|
35
|
+
summary_text = ::RSpec::Core::Formatters::Helpers.pluralize(summary.example_count, "example")
|
36
|
+
summary_text << ", " << ::RSpec::Core::Formatters::Helpers.pluralize(summary.failure_count, "failure")
|
37
|
+
summary_text << ", #{summary.pending_count} pending" if summary.pending_count > 0
|
38
|
+
summary_text << ", #{collector.total_objects} AR objects"
|
39
|
+
summary_text << ", #{collector.total_queries} AR queries"
|
40
|
+
|
41
|
+
summary_text
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,58 @@
|
|
1
|
+
class ActiveRecordDocumentationFormatter < ::RSpec::Core::Formatters::DocumentationFormatter
|
2
|
+
attr_reader :collector, :colorizer, :report
|
3
|
+
|
4
|
+
::RSpec::Core::Formatters.register self, :start, :dump_summary,
|
5
|
+
:example_started, :example_group_started,
|
6
|
+
:example_group_finished
|
7
|
+
|
8
|
+
def initialize(output)
|
9
|
+
super
|
10
|
+
|
11
|
+
@colorizer = ::RSpec::Core::Formatters::ConsoleCodes
|
12
|
+
@collector = ActiveRecordFormatterHelpers::Collector.new
|
13
|
+
@report = ActiveRecordFormatterHelpers::Report.new(collector)
|
14
|
+
end
|
15
|
+
|
16
|
+
def start(_start_notification)
|
17
|
+
output.puts "Recording and reporting ActiveRecord select and creation counts."
|
18
|
+
super
|
19
|
+
end
|
20
|
+
|
21
|
+
def example_group_started(example_group)
|
22
|
+
collector.group_started(example_group.group)
|
23
|
+
super
|
24
|
+
end
|
25
|
+
|
26
|
+
def example_group_finished(example_group)
|
27
|
+
collector.group_finished(example_group.group)
|
28
|
+
super
|
29
|
+
end
|
30
|
+
|
31
|
+
def example_started(example)
|
32
|
+
collector.reset_example(example)
|
33
|
+
end
|
34
|
+
|
35
|
+
def dump_summary(summary)
|
36
|
+
base = ActiveRecordFormatterBase.new(summary, collector)
|
37
|
+
output.puts base.colorized_summary
|
38
|
+
|
39
|
+
output.puts "\nOutputting Detailed Profile Data to #{report.report_path}"
|
40
|
+
report.write
|
41
|
+
end
|
42
|
+
|
43
|
+
protected
|
44
|
+
|
45
|
+
def passed_output(example)
|
46
|
+
"#{current_indentation}#{example_counts}" +
|
47
|
+
colorizer.wrap(example.description.strip, :success)
|
48
|
+
end
|
49
|
+
|
50
|
+
def failure_output(example)
|
51
|
+
"#{current_indentation}#{example_counts}" +
|
52
|
+
colorizer.wrap("#{example.description.strip} (FAILED - #{next_failure_index})", :failure)
|
53
|
+
end
|
54
|
+
|
55
|
+
def example_counts(suffix: " ")
|
56
|
+
"(%02d, %02d)#{suffix}" % [collector.objects_count, collector.query_count]
|
57
|
+
end
|
58
|
+
end
|
@@ -1,107 +1 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
class ActiveRecordFormatter < ::RSpec::Core::Formatters::DocumentationFormatter
|
4
|
-
attr_reader :collector, :colorizer, :configuration
|
5
|
-
|
6
|
-
::RSpec::Core::Formatters.register self, :start, :dump_summary,
|
7
|
-
:example_started, :example_group_started,
|
8
|
-
:example_group_finished
|
9
|
-
|
10
|
-
def initialize(output)
|
11
|
-
super
|
12
|
-
|
13
|
-
@colorizer = ::RSpec::Core::Formatters::ConsoleCodes
|
14
|
-
@collector = ActiveRecordFormatterHelpers::Collector.new
|
15
|
-
end
|
16
|
-
|
17
|
-
def start(start_notification)
|
18
|
-
output.puts "Recording and reporting ActiveRecord select and creation counts."
|
19
|
-
end
|
20
|
-
|
21
|
-
def example_group_started(example_group)
|
22
|
-
collector.group_started(example_group.group)
|
23
|
-
super
|
24
|
-
end
|
25
|
-
|
26
|
-
def example_group_finished(example_group)
|
27
|
-
collector.group_finished(example_group.group)
|
28
|
-
super
|
29
|
-
end
|
30
|
-
|
31
|
-
def example_started(example)
|
32
|
-
collector.reset_example(example)
|
33
|
-
end
|
34
|
-
|
35
|
-
def dump_summary(summary)
|
36
|
-
formatted = "\nFinished in #{summary.formatted_duration} " \
|
37
|
-
"(files took #{summary.formatted_load_time} to load)\n" \
|
38
|
-
"#{colorized_expanded_totals(summary)}\n"
|
39
|
-
|
40
|
-
unless summary.failed_examples.empty?
|
41
|
-
formatted << summary.colorized_rerun_commands(colorizer) << "\n"
|
42
|
-
end
|
43
|
-
|
44
|
-
output.puts formatted
|
45
|
-
write_profile_summary
|
46
|
-
end
|
47
|
-
|
48
|
-
def write_profile_summary
|
49
|
-
output_report_filename = Time.now.strftime("ar_%Y_%m_%d_%H_%m_%S.txt")
|
50
|
-
report_dir = Rails.root.join("tmp", "profile")
|
51
|
-
output_report_path = report_dir.join(output_report_filename)
|
52
|
-
|
53
|
-
output.puts "\nOutputting Detailed Profile Data to #{output_report_path}"
|
54
|
-
Dir.mkdir(report_dir) unless File.exists?(report_dir)
|
55
|
-
File.open(output_report_path, "wb") do |f|
|
56
|
-
f.puts "#{collector.total_objects} AR objects, #{collector.total_queries} AR queries"
|
57
|
-
|
58
|
-
f.puts ""
|
59
|
-
f.puts "Worst Example Groups by Object Creation"
|
60
|
-
collector.most_expensive_groups.first(50).each do |name, count|
|
61
|
-
f.puts "%-5s %s" % [count, name]
|
62
|
-
end
|
63
|
-
|
64
|
-
f.puts ""
|
65
|
-
f.puts "Most Common Queries"
|
66
|
-
collector.most_common_query_names.first(50).each do |name, count|
|
67
|
-
f.puts "%-5s %s" % [count, name]
|
68
|
-
end
|
69
|
-
end
|
70
|
-
end
|
71
|
-
|
72
|
-
protected
|
73
|
-
|
74
|
-
def passed_output(example)
|
75
|
-
"#{current_indentation}#{example_counts}" +
|
76
|
-
colorizer.wrap(example.description.strip, :success)
|
77
|
-
end
|
78
|
-
|
79
|
-
def failure_output(example)
|
80
|
-
"#{current_indentation}#{example_counts}" +
|
81
|
-
colorizer.wrap("#{example.description.strip} (FAILED - #{next_failure_index})", :failure)
|
82
|
-
end
|
83
|
-
|
84
|
-
def example_counts(suffix: " ")
|
85
|
-
"(%02d, %02d)#{suffix}" % [collector.objects_count, collector.query_count]
|
86
|
-
end
|
87
|
-
|
88
|
-
def colorized_expanded_totals(summary)
|
89
|
-
if summary.failure_count > 0
|
90
|
-
colorizer.wrap(expanded_totals_line(summary), RSpec.configuration.failure_color)
|
91
|
-
elsif summary.pending_count > 0
|
92
|
-
colorizer.wrap(expanded_totals_line(summary), RSpec.configuration.pending_color)
|
93
|
-
else
|
94
|
-
colorizer.wrap(expanded_totals_line(summary), RSpec.configuration.success_color)
|
95
|
-
end
|
96
|
-
end
|
97
|
-
|
98
|
-
def expanded_totals_line(summary)
|
99
|
-
summary_text = ::RSpec::Core::Formatters::Helpers.pluralize(summary.example_count, "example")
|
100
|
-
summary_text << ", " << ::RSpec::Core::Formatters::Helpers.pluralize(summary.failure_count, "failure")
|
101
|
-
summary_text << ", #{summary.pending_count} pending" if summary.pending_count > 0
|
102
|
-
summary_text << ", #{collector.total_objects} AR objects"
|
103
|
-
summary_text << ", #{collector.total_queries} AR queries"
|
104
|
-
|
105
|
-
summary_text
|
106
|
-
end
|
107
|
-
end
|
1
|
+
ActiveRecordFormatter = ActiveRecordDocumentationFormatter
|
@@ -0,0 +1,44 @@
|
|
1
|
+
module ActiveRecordFormatterHelpers
|
2
|
+
class Report
|
3
|
+
attr_reader :report_path, :default_path, :report_dir, :collector
|
4
|
+
|
5
|
+
def initialize(collector)
|
6
|
+
@collector = collector
|
7
|
+
|
8
|
+
@report_dir = Rails.root.join("tmp", "profile")
|
9
|
+
@report_path = report_dir.join(timestamped_filename)
|
10
|
+
@default_path = report_dir.join('ar_most_recent.txt')
|
11
|
+
end
|
12
|
+
|
13
|
+
def write
|
14
|
+
write_file(file_path: report_path)
|
15
|
+
write_file(file_path: default_path)
|
16
|
+
end
|
17
|
+
|
18
|
+
private
|
19
|
+
|
20
|
+
def timestamped_filename
|
21
|
+
Time.now.strftime("ar_%Y_%m_%d_%H_%m_%S.txt")
|
22
|
+
end
|
23
|
+
|
24
|
+
def write_file(file_path:)
|
25
|
+
Dir.mkdir(report_dir) unless File.exists?(report_dir)
|
26
|
+
|
27
|
+
File.open(file_path, "wb") do |f|
|
28
|
+
f.puts "#{collector.total_objects} AR objects, #{collector.total_queries} AR queries"
|
29
|
+
|
30
|
+
f.puts ""
|
31
|
+
f.puts "Worst Example Groups by Object Creation"
|
32
|
+
collector.most_expensive_groups.first(50).each do |name, count|
|
33
|
+
f.puts "%-5s %s" % [count, name]
|
34
|
+
end
|
35
|
+
|
36
|
+
f.puts ""
|
37
|
+
f.puts "Most Common Queries"
|
38
|
+
collector.most_common_query_names.first(50).each do |name, count|
|
39
|
+
f.puts "%-5s %s" % [count, name]
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
require_relative "helpers/collector"
|
2
|
+
require_relative "helpers/report"
|
3
|
+
|
4
|
+
class ActiveRecordProgressFormatter < ::RSpec::Core::Formatters::ProgressFormatter
|
5
|
+
attr_reader :collector, :colorizer, :report
|
6
|
+
|
7
|
+
::RSpec::Core::Formatters.register self, :start, :dump_summary,
|
8
|
+
:example_started, :example_group_started,
|
9
|
+
:example_group_finished
|
10
|
+
|
11
|
+
def initialize(output)
|
12
|
+
super
|
13
|
+
|
14
|
+
@colorizer = ::RSpec::Core::Formatters::ConsoleCodes
|
15
|
+
@collector = ActiveRecordFormatterHelpers::Collector.new
|
16
|
+
@report = ActiveRecordFormatterHelpers::Report.new(collector)
|
17
|
+
end
|
18
|
+
|
19
|
+
def start(_start_notification)
|
20
|
+
output.puts "Recording and reporting ActiveRecord select and creation counts."
|
21
|
+
super
|
22
|
+
end
|
23
|
+
|
24
|
+
def example_group_started(example_group)
|
25
|
+
collector.group_started(example_group.group)
|
26
|
+
super
|
27
|
+
end
|
28
|
+
|
29
|
+
def example_group_finished(example_group)
|
30
|
+
collector.group_finished(example_group.group)
|
31
|
+
end
|
32
|
+
|
33
|
+
def example_started(example)
|
34
|
+
collector.reset_example(example)
|
35
|
+
end
|
36
|
+
|
37
|
+
def dump_summary(summary)
|
38
|
+
base = ActiveRecordFormatterBase.new(summary, collector)
|
39
|
+
output.puts base.colorized_summary
|
40
|
+
|
41
|
+
output.puts "\nOutputting Detailed Profile Data to #{report.report_path}"
|
42
|
+
report.write
|
43
|
+
end
|
44
|
+
end
|
@@ -6,7 +6,7 @@ $LOAD_PATH << lib_dir unless $LOAD_PATH.include?(lib_dir)
|
|
6
6
|
Gem::Specification.new do |gem|
|
7
7
|
|
8
8
|
gem.name = "rspec-activerecord-formatter"
|
9
|
-
gem.version = "
|
9
|
+
gem.version = "2.0.0"
|
10
10
|
|
11
11
|
gem.summary = "Adds object creations and queries to Rspec output."
|
12
12
|
gem.description = "Creates a new formatter for ActiveRecord that can help you diagnose performance issues in RSpec"
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rspec-activerecord-formatter
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 2.0.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Joseph Mastey
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2019-07-
|
11
|
+
date: 2019-07-31 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activesupport
|
@@ -72,8 +72,12 @@ files:
|
|
72
72
|
- doc/images/demo_1.png
|
73
73
|
- doc/images/demo_2.png
|
74
74
|
- lib/rspec-activerecord-formatter.rb
|
75
|
+
- lib/rspec/activerecord/base.rb
|
76
|
+
- lib/rspec/activerecord/documentation_formatter.rb
|
75
77
|
- lib/rspec/activerecord/formatter.rb
|
76
78
|
- lib/rspec/activerecord/helpers/collector.rb
|
79
|
+
- lib/rspec/activerecord/helpers/report.rb
|
80
|
+
- lib/rspec/activerecord/progress_formatter.rb
|
77
81
|
- rspec-activerecord-formatter.gemspec
|
78
82
|
- spec/collector_spec.rb
|
79
83
|
- spec/formatter_spec.rb
|
@@ -98,7 +102,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
98
102
|
version: '0'
|
99
103
|
requirements: []
|
100
104
|
rubyforge_project:
|
101
|
-
rubygems_version: 2.
|
105
|
+
rubygems_version: 2.7.3
|
102
106
|
signing_key:
|
103
107
|
specification_version: 4
|
104
108
|
summary: Adds object creations and queries to Rspec output.
|