test-prof 1.0.3 → 1.0.4

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: c3ea5b7078b12209f32a60554f25acffccd184bdf852ebfe14cad161ded2c180
4
- data.tar.gz: 34e61ec6d58e5688b441ea09c1be524ae563f9ca82f334541c3f2c3197787cbd
3
+ metadata.gz: c90e1ef55e15100f84c70ca251e27113353a7998735966f56401fea543a43d1f
4
+ data.tar.gz: c91c7e49b98bb8904dcb18805bf38d8b9c1f29ea80559c037626dd5439929c32
5
5
  SHA512:
6
- metadata.gz: d866bfe03650d81cb2dd5b698b5de5703a8fa505c7c8d0b0e4283b8130eb774ac43c5cca6a750fef6f8342acdec7e518613489e898fd354f133e1793df833e45
7
- data.tar.gz: cf92cef8973837d2e09ff3bcc4449fb0675ebfca3f10fc75a314f10d885ad92aaae2f6fac0cd99e7250eb57985208e6d6f53b88d101f177709a172b8fcae1815
6
+ metadata.gz: d983f2986f990eb2a81064604dbd5f488bd34ffb80d74f2450cdf265601583062ba6eddc0746b6e10fa168b5aafe8c987350deb427198e011d937e27f210865e
7
+ data.tar.gz: 6c391a64e5d34ea094d81854bd03b142ae1e6bdf8040f9e3273430a26d7f92190e4455c2acb5db8ee6741b37b5a6529c0b2bee1fb871a884b0cf6e4bb1126b9e
data/CHANGELOG.md CHANGED
@@ -2,6 +2,30 @@
2
2
 
3
3
  ## master (unrealeased)
4
4
 
5
+ ## 1.0.4 (2021-05-12)
6
+
7
+ - Add ability to use custom logger. ([@palkan][])
8
+
9
+ ```ruby
10
+ TestProf.configure do |config|
11
+ config.logger = Logger.new($stdout, level: Logger::WARN)
12
+ end
13
+ ```
14
+
15
+ - Add `nate_heckler` mode for FactoryProf. ([@palkan][])
16
+
17
+ Drop this into your `rails_helper.rb` or `test_helper.rb`:
18
+
19
+ ```ruby
20
+ require "test_prof/factory_prof/nate_heckler"
21
+ ```
22
+
23
+ And for every test run see the overall factories usage:
24
+
25
+ ```sh
26
+ [TEST PROF INFO] Time spent in factories: 04:31.222 (54% of total time)
27
+ ```
28
+
5
29
  ## 1.0.3 (2021-04-30)
6
30
 
7
31
  - Minor fixes.
data/lib/test_prof.rb CHANGED
@@ -1,6 +1,8 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require "fileutils"
4
+ require "logger"
5
+
4
6
  require "test_prof/version"
5
7
  require "test_prof/logging"
6
8
  require "test_prof/utils"
@@ -130,7 +132,8 @@ module TestProf
130
132
 
131
133
  # TestProf configuration
132
134
  class Configuration
133
- attr_accessor :output, # IO to write output messages.
135
+ attr_accessor :output, # IO to write logs
136
+ :logger, # Logger instance to write to the output io
134
137
  :color, # Whether to colorize output or not
135
138
  :output_dir, # Directory to store artifacts
136
139
  :timestamps, # Whether to use timestamped names for artifacts,
@@ -138,6 +141,7 @@ module TestProf
138
141
 
139
142
  def initialize
140
143
  @output = $stdout
144
+ @logger = Logger.new(@output, formatter: Logging::Formatter.new)
141
145
  @color = true
142
146
  @output_dir = "tmp/test_prof"
143
147
  @timestamps = false
@@ -102,7 +102,7 @@ module TestProf
102
102
  def quoted(val)
103
103
  if val.is_a?(Array)
104
104
  val.map { |v| quoted(v) }
105
- elsif val.is_a?(ActiveRecord::Relation::QueryAttribute)
105
+ elsif val.is_a?(ActiveModel::Attribute)
106
106
  quoted(val.value_for_database)
107
107
  else
108
108
  ActiveRecord::Base.connection.quote(val)
@@ -2,6 +2,7 @@
2
2
 
3
3
  require "test_prof/factory_prof/printers/simple"
4
4
  require "test_prof/factory_prof/printers/flamegraph"
5
+ require "test_prof/factory_prof/printers/nate_heckler"
5
6
  require "test_prof/factory_prof/factory_builders/factory_bot"
6
7
  require "test_prof/factory_prof/factory_builders/fabrication"
7
8
 
@@ -14,10 +15,19 @@ module TestProf
14
15
 
15
16
  # FactoryProf configuration
16
17
  class Configuration
17
- attr_accessor :mode
18
+ attr_accessor :mode, :printer
18
19
 
19
20
  def initialize
20
21
  @mode = ENV["FPROF"] == "flamegraph" ? :flamegraph : :simple
22
+ @printer =
23
+ case ENV["FPROF"]
24
+ when "flamegraph"
25
+ Printers::Flamegraph
26
+ when "nate_heckler"
27
+ Printers::NateHeckler
28
+ else
29
+ Printers::Simple
30
+ end
21
31
  end
22
32
 
23
33
  # Whether we want to generate flamegraphs
@@ -74,7 +84,15 @@ module TestProf
74
84
 
75
85
  log :info, "FactoryProf enabled (#{config.mode} mode)"
76
86
 
87
+ patch!
88
+ end
89
+
90
+ def patch!
91
+ return if @patched
92
+
77
93
  FACTORY_BUILDERS.each(&:patch)
94
+
95
+ @patched = true
78
96
  end
79
97
 
80
98
  # Inits FactoryProf and setups at exit hook,
@@ -82,9 +100,11 @@ module TestProf
82
100
  def run
83
101
  init
84
102
 
85
- printer = config.flamegraph? ? Printers::Flamegraph : Printers::Simple
103
+ printer = config.printer
104
+
105
+ started_at = TestProf.now
86
106
 
87
- at_exit { printer.dump(result) }
107
+ at_exit { printer.dump(result, start_time: started_at) }
88
108
 
89
109
  start
90
110
  end
@@ -0,0 +1,16 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "test_prof/factory_prof"
4
+
5
+ # A standalone Factory Prof printer which is meant to be always enabled
6
+
7
+ TestProf::FactoryProf.patch!
8
+
9
+ started_at = TestProf.now
10
+ at_exit do
11
+ TestProf::FactoryProf::Printers::NateHeckler.dump(
12
+ TestProf::FactoryProf.result, start_time: started_at
13
+ )
14
+ end
15
+
16
+ TestProf::FactoryProf.start
@@ -11,7 +11,7 @@ module TestProf::FactoryProf
11
11
  class << self
12
12
  include TestProf::Logging
13
13
 
14
- def dump(result)
14
+ def dump(result, **)
15
15
  return log(:info, "No factories detected") if result.raw_stats == {}
16
16
  report_data = {
17
17
  total_stacks: result.stacks.size,
@@ -0,0 +1,26 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "test_prof/ext/float_duration"
4
+
5
+ module TestProf::FactoryProf
6
+ module Printers
7
+ # See https://twitter.com/nateberkopec/status/1389945187766456333
8
+ module NateHeckler # :nodoc: all
9
+ class << self
10
+ using TestProf::FloatDuration
11
+ include TestProf::Logging
12
+
13
+ def dump(result, start_time:)
14
+ return if result.raw_stats == {}
15
+
16
+ total_time = result.stats.sum { |stat| stat[:top_level_time] }
17
+ total_run_time = TestProf.now - start_time
18
+
19
+ percentage = ((total_time / total_run_time) * 100).round(2)
20
+
21
+ log :info, "Time spent in factories: #{total_time.duration} (#{percentage}% of total time)"
22
+ end
23
+ end
24
+ end
25
+ end
26
+ end
@@ -1,15 +1,19 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require "test_prof/ext/float_duration"
4
+
3
5
  module TestProf::FactoryProf
4
6
  module Printers
5
7
  module Simple # :nodoc: all
6
8
  class << self
9
+ using TestProf::FloatDuration
7
10
  include TestProf::Logging
8
11
 
9
- def dump(result)
12
+ def dump(result, start_time:)
10
13
  return log(:info, "No factories detected") if result.raw_stats == {}
11
14
  msgs = []
12
15
 
16
+ total_run_time = TestProf.now - start_time
13
17
  total_count = result.stats.sum { |stat| stat[:total_count] }
14
18
  total_top_level_count = result.stats.sum { |stat| stat[:top_level_count] }
15
19
  total_time = result.stats.sum { |stat| stat[:top_level_time] }
@@ -21,7 +25,7 @@ module TestProf::FactoryProf
21
25
 
22
26
  Total: #{total_count}
23
27
  Total top-level: #{total_top_level_count}
24
- Total time: #{format("%.4f", total_time)}s
28
+ Total time: #{total_time.duration} (out of #{total_run_time.duration})
25
29
  Total uniq factories: #{total_uniq_factories}
26
30
 
27
31
  total top-level total time time per call top-level time name
@@ -4,23 +4,29 @@ module TestProf
4
4
  # Helper for output printing
5
5
  module Logging
6
6
  COLORS = {
7
- info: "\e[34m", # blue
8
- warn: "\e[33m", # yellow
9
- error: "\e[31m" # red
7
+ INFO: "\e[34m", # blue
8
+ WARN: "\e[33m", # yellow
9
+ ERROR: "\e[31m" # red
10
10
  }.freeze
11
11
 
12
- def log(level, msg)
13
- TestProf.config.output.puts(build_log_msg(level, msg))
14
- end
12
+ class Formatter
13
+ def call(severity, _time, progname, msg)
14
+ colorize(severity.to_sym, "[#{progname} #{severity}] #{msg}")
15
+ end
15
16
 
16
- def build_log_msg(level, msg)
17
- colorize(level, "[TEST PROF #{level.to_s.upcase}] #{msg}")
18
- end
17
+ private
18
+
19
+ def colorize(level, msg)
20
+ return msg unless TestProf.config.color?
19
21
 
20
- def colorize(level, msg)
21
- return msg unless TestProf.config.color?
22
+ return msg unless COLORS.key?(level)
22
23
 
23
- "#{COLORS[level]}#{msg}\e[0m"
24
+ "#{COLORS[level]}#{msg}\e[0m"
25
+ end
26
+ end
27
+
28
+ def log(level, msg)
29
+ TestProf.config.logger.public_send(level, "TEST PROF") { msg }
24
30
  end
25
31
  end
26
32
  end
@@ -39,7 +39,7 @@ module TestProf
39
39
  acc << if v.nil?
40
40
  k.to_sym
41
41
  else
42
- Hash[k.to_sym, v.to_sym]
42
+ {k.to_sym => v.to_sym}
43
43
  end
44
44
  end
45
45
  end
@@ -12,7 +12,7 @@ module TestProf
12
12
 
13
13
  @data = Hash.new do |h, k|
14
14
  h[k] = {value: k, count: 0, time: 0.0}
15
- h[k].merge!(Hash[events.map { |event| [event, 0.0] }]) unless
15
+ h[k].merge!(events.map { |event| [event, 0.0] }.to_h) unless
16
16
  events.empty?
17
17
  h[k]
18
18
  end
@@ -53,11 +53,9 @@ module TestProf
53
53
  def fetch_events_data
54
54
  return {} unless @events_profiler
55
55
 
56
- Hash[
57
- @events_profiler.profilers.map do |profiler|
58
- [profiler.event, profiler.time]
59
- end
60
- ]
56
+ @events_profiler.profilers.map do |profiler|
57
+ [profiler.event, profiler.time]
58
+ end.to_h
61
59
  end
62
60
  end
63
61
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module TestProf
4
- VERSION = "1.0.3"
4
+ VERSION = "1.0.4"
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: test-prof
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.3
4
+ version: 1.0.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Vladimir Dementyev
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-04-30 00:00:00.000000000 Z
11
+ date: 2021-05-12 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -174,7 +174,9 @@ files:
174
174
  - lib/test_prof/factory_prof/factory_bot_patch.rb
175
175
  - lib/test_prof/factory_prof/factory_builders/fabrication.rb
176
176
  - lib/test_prof/factory_prof/factory_builders/factory_bot.rb
177
+ - lib/test_prof/factory_prof/nate_heckler.rb
177
178
  - lib/test_prof/factory_prof/printers/flamegraph.rb
179
+ - lib/test_prof/factory_prof/printers/nate_heckler.rb
178
180
  - lib/test_prof/factory_prof/printers/simple.rb
179
181
  - lib/test_prof/logging.rb
180
182
  - lib/test_prof/recipes/logging.rb
@@ -214,11 +216,12 @@ homepage: http://github.com/test-prof/test-prof
214
216
  licenses:
215
217
  - MIT
216
218
  metadata:
217
- bug_tracker_uri: http://github.com/test-prof/test-prof/issues
219
+ bug_tracker_uri: https://github.com/test-prof/test-prof/issues
218
220
  changelog_uri: https://github.com/test-prof/test-prof/blob/master/CHANGELOG.md
219
221
  documentation_uri: https://test-prof.evilmartians.io/
220
222
  homepage_uri: https://test-prof.evilmartians.io/
221
- source_code_uri: http://github.com/test-prof/test-prof
223
+ source_code_uri: https://github.com/test-prof/test-prof
224
+ funding_uri: https://github.com/sponsors/test-prof
222
225
  post_install_message:
223
226
  rdoc_options: []
224
227
  require_paths: