test-prof 1.0.6 → 1.0.9

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: f26a5003d400d430571206914f2f15a94ef4cca220c5f359e315eda7adf7a6b9
4
- data.tar.gz: 74d5cfb5e92351e628134dcd51230c6c984bd4b03518b89b4f98d8d20621e46f
3
+ metadata.gz: 9680aa33c1d917182a0be6e8cfd0656149d510b634db637b8023feda29f10886
4
+ data.tar.gz: 721767f61684ed87eff0f2e4c62080b9bb2a9e24bf6f47db194fc687bedbbe9b
5
5
  SHA512:
6
- metadata.gz: ea8cd4e7907fceb36874a91240be7baa0bdfb3c43dbddda21dececde541dbe5b9d52738ef3412c9c906e208fe5d33d2b34ce4e13a9063d941f360f2ccb845a30
7
- data.tar.gz: b87bec660bcd642dced3582c147317bb575628ef264eb7a33e31b59a1f5f7b740423fbd0a08dddf6c28638ffe266b460b05524cbfabbf95a93105053876aaf05
6
+ metadata.gz: 5a1d037cdac034f7c58f7bd090de128a81d41c3927787c953cacd33e8ecec1dd11cbda282f64fd542c2679b5176aa7bce4fe2ecb49806abac895d2cf9f478c00
7
+ data.tar.gz: baf837db1165a0d5631f07c9f4a978234afcce65fd9be886ef80bcf0a020fd43926e57eb5f295f0daddb22027c821ee72960fb01cd2cd4c7db6d18100d404343
data/CHANGELOG.md CHANGED
@@ -1,6 +1,28 @@
1
1
  # Change log
2
2
 
3
- ## master (unrealeased)
3
+ ## master (unreleased)
4
+
5
+ ## 1.0.9 (2022-05-05)
6
+
7
+ - Add `AnyFixture.before_fixtures_reset` and `AnyFixture.after_fixtures_reset` callbacks. ([@ruslanshakirov][])
8
+
9
+ - Fixes ActiveRecord 6.1 issue with AnyFixture and Postgres config ([@markedmondson][])
10
+
11
+ ## 1.0.8 (2022-03-11)
12
+
13
+ - Restore the lock_thread value after rollback. ([@cou929][])
14
+
15
+ - Fixes the configuration of a printer for factory_prof runs
16
+
17
+ - Ensure that defaults are stored in a threadsafe manner
18
+
19
+ ## 1.0.7 (2021-08-30)
20
+
21
+ - Fix access to `let_it_be` variables in `after(:all)` hook. ([@cbarton][])
22
+
23
+ - Add support for using the before_all hook with Rails' parallelize feature (using processes). ([@peret][])
24
+
25
+ Make sure to include `TestProf::BeforeAll::Minitest` before you call `parallelize`.
4
26
 
5
27
  ## 1.0.6 (2021-06-23)
6
28
 
@@ -259,3 +281,6 @@ See [changelog](https://github.com/test-prof/test-prof/blob/v0.8.0/CHANGELOG.md)
259
281
  [@stefkin]: https://github.com/stefkin
260
282
  [@jaimerson]: https://github.com/jaimerson
261
283
  [@alexvko]: https://github.com/alexvko
284
+ [@grillermo]: https://github.com/grillermo
285
+ [@cou929]: https://github.com/cou929
286
+ [@ruslanshakirov]: https://github.com/ruslanshakirov
@@ -2,7 +2,7 @@
2
2
 
3
3
  module TestProf
4
4
  module AnyFixture
5
- # Adds "global" `fixture` method (through refinement)
5
+ # Adds "global" `fixture`, `before_fixtures_reset` and `after_fixtures_reset` methods (through refinement)
6
6
  module DSL
7
7
  # Refine object, 'cause refining modules (Kernel) is vulnerable to prepend:
8
8
  # - https://bugs.ruby-lang.org/issues/13446
@@ -11,6 +11,14 @@ module TestProf
11
11
  def fixture(id, &block)
12
12
  ::TestProf::AnyFixture.register(:"#{id}", &block)
13
13
  end
14
+
15
+ def before_fixtures_reset(&block)
16
+ ::TestProf::AnyFixture.before_fixtures_reset(&block)
17
+ end
18
+
19
+ def after_fixtures_reset(&block)
20
+ ::TestProf::AnyFixture.after_fixtures_reset(&block)
21
+ end
14
22
  end
15
23
  end
16
24
  end
@@ -23,14 +23,14 @@ module TestProf
23
23
  end
24
24
 
25
25
  def compile_sql(sql, binds)
26
- sql.gsub(/\$\d+/) { binds.shift }
26
+ sql.gsub(/\$\d+/) { binds.shift.gsub("\n", "' || chr(10) || '") }
27
27
  end
28
28
 
29
29
  def import(path)
30
30
  # Test if psql is installed
31
31
  `psql --version`
32
32
 
33
- tasks = ActiveRecord::Tasks::PostgreSQLDatabaseTasks.new(conn.pool.spec.config.with_indifferent_access)
33
+ tasks = ActiveRecord::Tasks::PostgreSQLDatabaseTasks.new(config)
34
34
 
35
35
  while_disconnected do
36
36
  tasks.structure_load(path, "--output=/dev/null")
@@ -85,6 +85,15 @@ module TestProf
85
85
  def execute(query)
86
86
  super.values
87
87
  end
88
+
89
+ def config
90
+ conn_pool = conn.pool
91
+ if conn_pool.respond_to?(:spec) # Support for Rails < 6.1
92
+ conn_pool.spec.config
93
+ else
94
+ conn_pool.db_config
95
+ end
96
+ end
88
97
  end
89
98
  end
90
99
  end
@@ -18,7 +18,7 @@ module TestProf
18
18
  end
19
19
 
20
20
  def compile_sql(sql, binds)
21
- sql.gsub(/\?/) { binds.shift }
21
+ sql.gsub(/\?/) { binds.shift.gsub("\n", "' || char(10) || '") }
22
22
  end
23
23
 
24
24
  def import(path)
@@ -1,5 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require "test_prof"
3
4
  require "test_prof/ext/float_duration"
4
5
  require "test_prof/any_fixture/dump"
5
6
 
@@ -118,6 +119,8 @@ module TestProf
118
119
  # returns the result of the block execution
119
120
  def register(id)
120
121
  cached(id) do
122
+ raise "No fixture named #{id} has been registered" unless block_given?
123
+
121
124
  ActiveSupport::Notifications.subscribed(method(:subscriber), "sql.active_record") do
122
125
  yield
123
126
  end
@@ -174,9 +177,22 @@ module TestProf
174
177
 
175
178
  # Reset all information and clean tables
176
179
  def reset
180
+ callbacks[:before_fixtures_reset].each(&:call)
181
+
177
182
  clean
178
183
  tables_cache.clear
179
184
  cache.clear
185
+
186
+ callbacks[:after_fixtures_reset].each(&:call)
187
+ callbacks.clear
188
+ end
189
+
190
+ def before_fixtures_reset(&block)
191
+ callbacks[:before_fixtures_reset] << block
192
+ end
193
+
194
+ def after_fixtures_reset(&block)
195
+ callbacks[:after_fixtures_reset] << block
180
196
  end
181
197
 
182
198
  def subscriber(_event, _start, _finish, _id, data)
@@ -253,6 +269,10 @@ module TestProf
253
269
  @tables_cache ||= {}
254
270
  end
255
271
 
272
+ def callbacks
273
+ @callbacks ||= Hash.new { |h, k| h[k] = [] }
274
+ end
275
+
256
276
  def disable_referential_integrity
257
277
  connection = ActiveRecord::Base.connection
258
278
  return yield unless connection.respond_to?(:disable_referential_integrity)
@@ -37,6 +37,9 @@ module TestProf
37
37
  end
38
38
  end
39
39
 
40
+ # avoid instance variable collisions with cats
41
+ PREFIX_RESTORE_LOCK_THREAD = "@😺"
42
+
40
43
  configure do |config|
41
44
  # Make sure ActiveRecord uses locked thread.
42
45
  # It only gets locked in `before` / `setup` hook,
@@ -44,8 +47,14 @@ module TestProf
44
47
  # might lead to leaking connections
45
48
  config.before(:begin) do
46
49
  next unless ::ActiveRecord::Base.connection.pool.respond_to?(:lock_thread=)
50
+ instance_variable_set("#{PREFIX_RESTORE_LOCK_THREAD}_orig_lock_thread", ::ActiveRecord::Base.connection.pool.instance_variable_get(:@lock_thread))
47
51
  ::ActiveRecord::Base.connection.pool.lock_thread = true
48
52
  end
53
+
54
+ config.after(:rollback) do
55
+ next unless ::ActiveRecord::Base.connection.pool.respond_to?(:lock_thread=)
56
+ ::ActiveRecord::Base.connection.pool.lock_thread = instance_variable_get("#{PREFIX_RESTORE_LOCK_THREAD}_orig_lock_thread")
57
+ end
49
58
  end
50
59
  end
51
60
  end
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require "test_prof"
4
+
3
5
  module TestProf
4
6
  # `before_all` helper configuration
5
7
  module BeforeAll
@@ -48,14 +48,15 @@ module RuboCop
48
48
 
49
49
  def transform_its(body, arguments)
50
50
  argument = arguments.first
51
- replacement = case argument.type
52
- when :array
53
- key = argument.values.first
54
- "expect(subject[#{key.source}])"
55
- else
56
- property = argument.value
57
- "expect(subject.#{property})"
58
- end
51
+ replacement =
52
+ case argument.type
53
+ when :array
54
+ key = argument.values.first
55
+ "expect(subject[#{key.source}])"
56
+ else
57
+ property = argument.value
58
+ "expect(subject.#{property})"
59
+ end
59
60
  body.source.gsub(/is_expected|are_expected/, replacement)
60
61
  end
61
62
 
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require_relative "../language"
3
+ require "test_prof/cops/rspec/language"
4
4
 
5
5
  module RuboCop
6
6
  module Cop
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require_relative "../language"
3
+ require "test_prof/cops/rspec/language"
4
4
 
5
5
  module RuboCop
6
6
  module Cop
@@ -1,11 +1,11 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require_relative "aggregate_examples/line_range_helpers"
4
- require_relative "aggregate_examples/metadata_helpers"
5
- require_relative "aggregate_examples/node_matchers"
3
+ require "test_prof/cops/rspec/aggregate_examples/line_range_helpers"
4
+ require "test_prof/cops/rspec/aggregate_examples/metadata_helpers"
5
+ require "test_prof/cops/rspec/aggregate_examples/node_matchers"
6
6
 
7
- require_relative "aggregate_examples/its"
8
- require_relative "aggregate_examples/matchers_with_side_effects"
7
+ require "test_prof/cops/rspec/aggregate_examples/its"
8
+ require "test_prof/cops/rspec/aggregate_examples/matchers_with_side_effects"
9
9
 
10
10
  module RuboCop
11
11
  module Cop
@@ -1,5 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require "test_prof"
3
4
  require "test_prof/factory_bot"
4
5
  require "test_prof/factory_all_stub/factory_bot_patch"
5
6
 
@@ -1,5 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require "test_prof"
3
4
  require "test_prof/factory_bot"
4
5
  require "test_prof/factory_default/factory_bot_patch"
5
6
 
@@ -31,7 +32,6 @@ module TestProf
31
32
  TestProf::FactoryBot::Strategy::Build.prepend StrategyExt
32
33
  TestProf::FactoryBot::Strategy::Stub.prepend StrategyExt
33
34
 
34
- @store = {}
35
35
  # default is false to retain backward compatibility
36
36
  @preserve_traits = false
37
37
  end
@@ -57,12 +57,14 @@ module TestProf
57
57
  end
58
58
 
59
59
  def reset
60
- @store.clear
60
+ store.clear
61
61
  end
62
62
 
63
63
  private
64
64
 
65
- attr_reader :store
65
+ def store
66
+ Thread.current[:testprof_factory_store] ||= {}
67
+ end
66
68
  end
67
69
  end
68
70
  end
@@ -100,15 +100,21 @@ module TestProf
100
100
  def run
101
101
  init
102
102
 
103
- printer = config.printer
104
-
105
103
  started_at = TestProf.now
106
104
 
107
- at_exit { printer.dump(result, start_time: started_at) }
105
+ at_exit do
106
+ print(started_at)
107
+ end
108
108
 
109
109
  start
110
110
  end
111
111
 
112
+ def print(started_at)
113
+ printer = config.printer
114
+
115
+ printer.dump(result, start_time: started_at)
116
+ end
117
+
112
118
  def start
113
119
  reset!
114
120
  @running = true
@@ -24,8 +24,6 @@ module TestProf
24
24
  ]
25
25
  end
26
26
 
27
- # rubocop:disable Metrics/CyclomaticComplexity
28
- # rubocop:disable Metrics/PerceivedComplexity
29
27
  def all_loggables
30
28
  return @all_loggables if instance_variable_defined?(:@all_loggables)
31
29
 
@@ -2,6 +2,22 @@
2
2
 
3
3
  require "test_prof/before_all"
4
4
 
5
+ Minitest.singleton_class.prepend(Module.new do
6
+ attr_reader :previous_klass
7
+ @previous_klass = nil
8
+
9
+ def run_one_method(klass, method_name)
10
+ return super unless klass.respond_to?(:parallelized) && klass.parallelized
11
+
12
+ if @previous_klass && @previous_klass != klass
13
+ @previous_klass.before_all_executor&.deactivate!
14
+ end
15
+ @previous_klass = klass
16
+
17
+ super
18
+ end
19
+ end)
20
+
5
21
  module TestProf
6
22
  module BeforeAll
7
23
  # Add before_all hook to Minitest: wrap all examples into a transaction and
@@ -83,6 +99,38 @@ module TestProf
83
99
  class << self
84
100
  def included(base)
85
101
  base.extend ClassMethods
102
+
103
+ base.cattr_accessor :parallelized
104
+ if base.respond_to?(:parallelize_teardown)
105
+ base.parallelize_teardown do
106
+ last_klass = ::Minitest.previous_klass
107
+ if last_klass&.respond_to?(:parallelized) && last_klass&.parallelized
108
+ last_klass.before_all_executor&.deactivate!
109
+ end
110
+ end
111
+ end
112
+
113
+ if base.respond_to?(:parallelize)
114
+ base.singleton_class.prepend(Module.new do
115
+ def parallelize(workers: :number_of_processors, with: :processes)
116
+ # super.parallelize returns nil when no parallelization is set up
117
+ if super(workers: workers, with: with).nil?
118
+ return
119
+ end
120
+
121
+ case with
122
+ when :processes
123
+ self.parallelized = true
124
+ when :threads
125
+ warn "!!! before_all is not implemented for parallalization with threads and " \
126
+ "could work incorrectly"
127
+ else
128
+ warn "!!! tests are using an unknown parallelization strategy and before_all " \
129
+ "could work incorrectly"
130
+ end
131
+ end
132
+ end)
133
+ end
86
134
  end
87
135
  end
88
136
 
@@ -118,7 +166,7 @@ module TestProf
118
166
  def run(*)
119
167
  super
120
168
  ensure
121
- before_all_executor&.deactivate!
169
+ before_all_executor&.deactivate! unless parallelized
122
170
  end
123
171
  end)
124
172
  end
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require "test_prof"
4
- require_relative "./before_all"
4
+ require "test_prof/recipes/rspec/before_all"
5
5
 
6
6
  module TestProf
7
7
  # Just like `let`, but persist the result for the whole group.
@@ -75,7 +75,7 @@ module TestProf
75
75
  # Use uniq prefix for instance variables to avoid collisions
76
76
  # We want to use the power of Ruby's unicode support)
77
77
  # And we love cats!)
78
- PREFIX = RUBY_ENGINE == "jruby" ? "@__jruby_is_not_cat_friendly__" : "@😸"
78
+ PREFIX = "@😸"
79
79
 
80
80
  FROZEN_ERROR_HINT = "\nIf you are using `let_it_be`, you may want to pass `reload: true` or `refind: true` modifier to it."
81
81
 
@@ -107,7 +107,7 @@ module TestProf
107
107
  define_method(identifier) do
108
108
  # Trying to detect the context
109
109
  # Based on https://github.com/rspec/rspec-rails/commit/7cb796db064f58da7790a92e73ab906ef50b1f34
110
- if @__inspect_output.include?("before(:context)") || @__inspect_output.include?("before_all")
110
+ if /(before|after)\(:context\)/.match?(@__inspect_output) || @__inspect_output.include?("before_all")
111
111
  instance_variable_get(:"#{PREFIX}#{identifier}")
112
112
  else
113
113
  # Fallback to let definition
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require_relative "./base"
3
+ require "test_prof/rspec_dissect/collectors/base"
4
4
 
5
5
  module TestProf
6
6
  module RSpecDissect
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require_relative "./base"
3
+ require "test_prof/rspec_dissect/collectors/base"
4
4
 
5
5
  module TestProf
6
6
  module RSpecDissect
@@ -28,8 +28,6 @@ module TestProf
28
28
  end
29
29
 
30
30
  class << self
31
- # rubocop: disable Metrics/CyclomaticComplexity
32
- # rubocop: disable Metrics/PerceivedComplexity
33
31
  def parse(code)
34
32
  sexp = Ripper.sexp(code)
35
33
  return unless sexp
@@ -116,8 +116,6 @@ module TestProf
116
116
 
117
117
  private
118
118
 
119
- # rubocop: disable Metrics/CyclomaticComplexity
120
- # rubocop: disable Metrics/PerceivedComplexity
121
119
  def stamp_example(example, tags)
122
120
  matches = example.match(EXAMPLE_RXP)
123
121
  return false unless matches
@@ -9,5 +9,5 @@ end
9
9
 
10
10
  require "rubocop"
11
11
 
12
- require_relative "cops/inject"
12
+ require "test_prof/cops/inject"
13
13
  require "test_prof/cops/rspec/aggregate_examples"
@@ -162,13 +162,13 @@ module TestProf
162
162
  log :info, <<~MSG
163
163
  Run the following command to generate a flame graph report:
164
164
 
165
- stackprof --flamegraph #{path} > #{html_path} && stackprof --flamegraph-viewer=#{html_path}
165
+ stackprof --d3-flamegraph #{path} > #{html_path} && stackprof --flamegraph-viewer=#{html_path}
166
166
  MSG
167
167
  end
168
168
 
169
169
  def dump_json_report(path)
170
170
  report = ::StackProf::Report.new(
171
- Marshal.load(IO.binread(path)) # rubocop:disable Security/MarshalLoad
171
+ Marshal.load(IO.binread(path))
172
172
  )
173
173
  json_path = path.gsub(/\.dump$/, ".json")
174
174
  File.write(json_path, JSON.generate(report.data))
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module TestProf
4
- VERSION = "1.0.6"
4
+ VERSION = "1.0.9"
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.6
4
+ version: 1.0.9
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-06-23 00:00:00.000000000 Z
11
+ date: 2022-05-06 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -237,7 +237,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
237
237
  - !ruby/object:Gem::Version
238
238
  version: '0'
239
239
  requirements: []
240
- rubygems_version: 3.2.15
240
+ rubygems_version: 3.3.7
241
241
  signing_key:
242
242
  specification_version: 4
243
243
  summary: Ruby applications tests profiling tools