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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 573d9da6bd2d49e858ad2598ecf931c7b9909cc4d53881ed84d27b9e071310c5
4
- data.tar.gz: a4f40473db9a50e226ba87b5512b031a1adacf5694f1872ef1571763e997f212
3
+ metadata.gz: db1b2dbddfb326ac8143998c1b7cc204d90d84f83ccfabe9f3cc022d435a49d8
4
+ data.tar.gz: 7f29a63684b8e1ce6614e99cbf6ad978739f2f08357d14abc7a4209f2fd866ea
5
5
  SHA512:
6
- metadata.gz: 87e83e43deaad1f964e3cc88264ab51779a0362c789f18a5ea3d33d1116059866f7f3df0c8946f936462215b94a8f4440bafb1f11143bf5a7d5a2f964a62f433
7
- data.tar.gz: '068fbce81ae37fe58c1e0d97d61f4024cab3cd233618f870d8e4b842d25291810872504dc53c21e702379a92a4aca472dde66fbdb7869a7d57a6ef1524dac255'
6
+ metadata.gz: 9f7f871268d7ce2c007d1bede488b073e443ee5e93ae6ed9f07ca7e787811b2bd38d373ca5843c34403dc877942c1b7908f83ed9729f6c5010f71801dbced20d
7
+ data.tar.gz: 5dc551ee718ce1fdd0e5ce8997f105750b2295d2e7a9b14e399acce10ee5a17be8a07b76bd51c8d21c30b8c2278337b224cb0d8dda5916977f8082040e72a07a
data/.gitignore CHANGED
@@ -1,3 +1,4 @@
1
1
  .DS_Store
2
2
  Gemfile.lock
3
3
  coverage
4
+ *.gem
@@ -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, :example_passed, :example_failed
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("rspec_activerecord_result_%Y_%m_%d_%H_%m_%S.txt")
39
- output_report_path = Rails.root.join("tmp", output_report_filename)
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\n"
44
- f.puts "Query Summary"
45
- collector.most_common_query_names.each do |name, count|
46
- f.puts "%-4s %s" % [count, name]
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, :query_names
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
- @query_count += 1
22
- @total_queries += 1
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
- @query_names.sort_by(&:last).reverse
31
+ query_names.sort_by(&:last).reverse
35
32
  end
36
33
 
37
- def reset_example
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.1.0"
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"
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rspec-activerecord-formatter
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.1.0
4
+ version: 1.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Joseph Mastey