rspec-activerecord-formatter 1.1.0 → 1.2.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 +4 -4
- data/.gitignore +1 -0
- data/lib/rspec/activerecord/formatter.rb +30 -9
- data/lib/rspec/activerecord/helpers/collector.rb +48 -13
- data/rspec-activerecord-formatter.gemspec +1 -1
- metadata +1 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: db1b2dbddfb326ac8143998c1b7cc204d90d84f83ccfabe9f3cc022d435a49d8
|
4
|
+
data.tar.gz: 7f29a63684b8e1ce6614e99cbf6ad978739f2f08357d14abc7a4209f2fd866ea
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 9f7f871268d7ce2c007d1bede488b073e443ee5e93ae6ed9f07ca7e787811b2bd38d373ca5843c34403dc877942c1b7908f83ed9729f6c5010f71801dbced20d
|
7
|
+
data.tar.gz: 5dc551ee718ce1fdd0e5ce8997f105750b2295d2e7a9b14e399acce10ee5a17be8a07b76bd51c8d21c30b8c2278337b224cb0d8dda5916977f8082040e72a07a
|
data/.gitignore
CHANGED
@@ -4,7 +4,8 @@ class ActiveRecordFormatter < ::RSpec::Core::Formatters::DocumentationFormatter
|
|
4
4
|
attr_reader :collector, :colorizer, :configuration
|
5
5
|
|
6
6
|
::RSpec::Core::Formatters.register self, :start, :dump_summary,
|
7
|
-
:example_started, :
|
7
|
+
:example_started, :example_group_started,
|
8
|
+
:example_group_finished
|
8
9
|
|
9
10
|
def initialize(output)
|
10
11
|
super
|
@@ -17,8 +18,18 @@ class ActiveRecordFormatter < ::RSpec::Core::Formatters::DocumentationFormatter
|
|
17
18
|
output.puts "Recording and reporting ActiveRecord select and creation counts."
|
18
19
|
end
|
19
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
|
+
|
20
31
|
def example_started(example)
|
21
|
-
collector.reset_example
|
32
|
+
collector.reset_example(example)
|
22
33
|
end
|
23
34
|
|
24
35
|
def dump_summary(summary)
|
@@ -35,15 +46,25 @@ class ActiveRecordFormatter < ::RSpec::Core::Formatters::DocumentationFormatter
|
|
35
46
|
end
|
36
47
|
|
37
48
|
def write_profile_summary
|
38
|
-
output_report_filename = Time.now.strftime("
|
39
|
-
|
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)
|
40
52
|
|
41
|
-
puts "\nOutputting Detailed Profile Data to #{output_report_path}"
|
53
|
+
output.puts "\nOutputting Detailed Profile Data to #{output_report_path}"
|
54
|
+
Dir.mkdir(report_dir) unless File.exists?(report_dir)
|
42
55
|
File.open(output_report_path, "wb") do |f|
|
43
|
-
f.puts "#{collector.total_objects} AR objects, #{collector.total_queries} AR queries
|
44
|
-
|
45
|
-
|
46
|
-
|
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]
|
47
68
|
end
|
48
69
|
end
|
49
70
|
end
|
@@ -2,7 +2,9 @@ require 'active_support/notifications'
|
|
2
2
|
|
3
3
|
module ActiveRecordFormatterHelpers
|
4
4
|
class Collector
|
5
|
-
attr_reader :query_count, :objects_count, :total_queries, :total_objects,
|
5
|
+
attr_reader :query_count, :objects_count, :total_queries, :total_objects,
|
6
|
+
:query_names, :active_groups, :group_counts
|
7
|
+
|
6
8
|
SKIP_QUERIES = ["SELECT tablename FROM pg_tables", "select sum(ct) from (select count(*) ct from"]
|
7
9
|
|
8
10
|
def initialize
|
@@ -11,6 +13,8 @@ module ActiveRecordFormatterHelpers
|
|
11
13
|
@total_queries = 0
|
12
14
|
@total_objects = 0
|
13
15
|
@query_names = Hash.new(0)
|
16
|
+
@group_counts = Hash.new(0)
|
17
|
+
@active_groups = []
|
14
18
|
|
15
19
|
ActiveSupport::Notifications.subscribe("sql.active_record", method(:record_query))
|
16
20
|
end
|
@@ -18,29 +22,60 @@ module ActiveRecordFormatterHelpers
|
|
18
22
|
def record_query(*_unused, data)
|
19
23
|
return if SKIP_QUERIES.any? { |q| data[:sql].index(q) == 0 }
|
20
24
|
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
if query_is_an_insert?(data[:sql])
|
25
|
-
@objects_count += 1
|
26
|
-
@total_objects += 1
|
27
|
-
end
|
28
|
-
|
29
|
-
name = data[:name] || "Unnamed"
|
30
|
-
@query_names[name] += 1
|
25
|
+
inc_query
|
26
|
+
inc_object if query_is_an_insert?(data[:sql])
|
27
|
+
inc_query_name(data)
|
31
28
|
end
|
32
29
|
|
33
30
|
def most_common_query_names
|
34
|
-
|
31
|
+
query_names.sort_by(&:last).reverse
|
35
32
|
end
|
36
33
|
|
37
|
-
def
|
34
|
+
def most_expensive_groups
|
35
|
+
group_counts.sort_by(&:last).reverse
|
36
|
+
end
|
37
|
+
|
38
|
+
def reset_example(_)
|
38
39
|
@query_count = 0
|
39
40
|
@objects_count = 0
|
40
41
|
end
|
41
42
|
|
43
|
+
def group_started(group)
|
44
|
+
return unless group.parent_groups.length > 1
|
45
|
+
|
46
|
+
active_groups.push(group_path(group))
|
47
|
+
end
|
48
|
+
|
49
|
+
def group_finished(group)
|
50
|
+
active_groups.delete(group_path(group))
|
51
|
+
end
|
52
|
+
|
42
53
|
protected
|
43
54
|
|
55
|
+
def inc_object
|
56
|
+
@objects_count += 1
|
57
|
+
@total_objects += 1
|
58
|
+
|
59
|
+
active_groups.each do |group|
|
60
|
+
@group_counts[group] += 1
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
def inc_query
|
65
|
+
@query_count += 1
|
66
|
+
@total_queries += 1
|
67
|
+
end
|
68
|
+
|
69
|
+
def inc_query_name(data)
|
70
|
+
name = data[:name] || "Unnamed"
|
71
|
+
|
72
|
+
query_names[name] += 1
|
73
|
+
end
|
74
|
+
|
75
|
+
def group_path(group)
|
76
|
+
group.parent_groups.reverse.map(&:description).join(' ')
|
77
|
+
end
|
78
|
+
|
44
79
|
# TODO: what happens if we try to create many records at once?
|
45
80
|
# TODO: are there any false positives we need to worry about? false negatives?
|
46
81
|
def query_is_an_insert?(query)
|
@@ -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 = "1.
|
9
|
+
gem.version = "1.2.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"
|