test-prof 1.3.0 → 1.4.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 +4 -4
- data/CHANGELOG.md +78 -0
- data/README.md +2 -2
- data/lib/minitest/test_prof_plugin.rb +3 -0
- data/lib/test_prof/any_fixture/dsl.rb +19 -1
- data/lib/test_prof/any_fixture/dump.rb +1 -1
- data/lib/test_prof/any_fixture.rb +16 -2
- data/lib/test_prof/before_all/adapters/active_record.rb +82 -47
- data/lib/test_prof/before_all/isolator.rb +6 -15
- data/lib/test_prof/before_all.rb +31 -8
- data/lib/test_prof/cops/rspec/aggregate_examples/its.rb +2 -2
- data/lib/test_prof/cops/rspec/aggregate_examples/line_range_helpers.rb +1 -1
- data/lib/test_prof/cops/rspec/aggregate_examples/matchers_with_side_effects.rb +1 -1
- data/lib/test_prof/cops/rspec/aggregate_examples/metadata_helpers.rb +1 -1
- data/lib/test_prof/cops/rspec/aggregate_examples/node_matchers.rb +1 -1
- data/lib/test_prof/cops/rspec/aggregate_examples.rb +12 -18
- data/lib/test_prof/core.rb +28 -1
- data/lib/test_prof/event_prof/monitor.rb +3 -10
- data/lib/test_prof/ext/active_record_refind.rb +1 -1
- data/lib/test_prof/ext/string_truncate.rb +1 -1
- data/lib/test_prof/factory_bot.rb +2 -0
- data/lib/test_prof/factory_default/fabrication_patch.rb +60 -0
- data/lib/test_prof/factory_default/factory_bot_patch.rb +59 -9
- data/lib/test_prof/factory_default.rb +11 -39
- data/lib/test_prof/factory_doctor.rb +1 -2
- data/lib/test_prof/factory_prof/fabrication_patch.rb +7 -1
- data/lib/test_prof/factory_prof/factory_bot_patch.rb +15 -1
- data/lib/test_prof/factory_prof/factory_builders/fabrication.rb +2 -2
- data/lib/test_prof/factory_prof/factory_builders/factory_bot.rb +2 -2
- data/lib/test_prof/factory_prof/printers/json.rb +41 -0
- data/lib/test_prof/factory_prof/printers/nate_heckler.rb +1 -1
- data/lib/test_prof/factory_prof/printers/simple.rb +23 -4
- data/lib/test_prof/factory_prof.rb +57 -25
- data/lib/test_prof/memory_prof/printer.rb +2 -0
- data/lib/test_prof/memory_prof/rspec.rb +7 -4
- data/lib/test_prof/memory_prof/tracker/linked_list.rb +8 -6
- data/lib/test_prof/memory_prof/tracker.rb +14 -10
- data/lib/test_prof/recipes/minitest/before_all.rb +2 -2
- data/lib/test_prof/recipes/minitest/sample.rb +14 -5
- data/lib/test_prof/recipes/rspec/any_fixture.rb +8 -0
- data/lib/test_prof/recipes/rspec/let_it_be.rb +19 -0
- data/lib/test_prof/rspec_stamp/parser.rb +1 -1
- data/lib/test_prof/rspec_stamp.rb +7 -5
- data/lib/test_prof/ruby_prof/rspec_no_boot.rb +15 -0
- data/lib/test_prof/ruby_prof.rb +20 -7
- data/lib/test_prof/tag_prof/minitest.rb +74 -0
- data/lib/test_prof/tag_prof/result.rb +2 -2
- data/lib/test_prof/tps_prof/profiler.rb +55 -0
- data/lib/test_prof/tps_prof/reporter/text.rb +48 -0
- data/lib/test_prof/tps_prof/rspec.rb +63 -0
- data/lib/test_prof/tps_prof.rb +46 -0
- data/lib/test_prof/vernier.rb +3 -1
- data/lib/test_prof/version.rb +1 -1
- data/lib/test_prof.rb +1 -0
- metadata +15 -7
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 3cfa0f1751f398092de8ffa46d5bff81bb9eadd7b90caaf9293c62c93c6b3e20
|
4
|
+
data.tar.gz: 3afcb831782f0e58881839f33af07a41b3b42d63ac8eb87c35b6fd0eb01537ea
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 2de8fb8232f5ed623167846c37cce6224b297761324acdf6a17a47338e2a3904aa480b48fc9793a51f5595d3d839c3ff3bc9fbb262c7900ad3d7c819113947a0
|
7
|
+
data.tar.gz: dcec92d722f9e7cce9f1d371a2c6d363aa9a78a6cf1149a73d8b836a269ebf6bd14e50d86a8470cccc56a861b94646ad23494f43de6d9beb0cc6a5b478f77e93
|
data/CHANGELOG.md
CHANGED
@@ -2,6 +2,78 @@
|
|
2
2
|
|
3
3
|
## master (unreleased)
|
4
4
|
|
5
|
+
## 1.4.4 (2025-01-03)
|
6
|
+
|
7
|
+
- Fix _stamping_ specs with single quotes with Rpsec Stamp. ([@elasticspoon][])
|
8
|
+
|
9
|
+
## 1.4.3 (2024-12-18)
|
10
|
+
|
11
|
+
- Fix handling new (lazy) connection pools in `before_all`. ([@palkan][])
|
12
|
+
|
13
|
+
- Updates Rubocop::Cop code to comply with most modern API. ([@aseroff][])
|
14
|
+
|
15
|
+
## 1.4.2 (2024-09-03) 🗓️
|
16
|
+
|
17
|
+
- Ignore default scopes in `ActiveRecord::Base#refind`. ([@palkan][])
|
18
|
+
|
19
|
+
## 1.4.1 (2024-08-23)
|
20
|
+
|
21
|
+
- Skips loading the ActiveRecord adapter for runs where RSpec --dry-run mode is enabled. ([@devinburnette][])
|
22
|
+
|
23
|
+
## 1.4.0 (2024-08-12)
|
24
|
+
|
25
|
+
- AnyFixture: Disable fixtures cache within _clean fixture_ context. Automatically _refind_ records when using `#fixture`. ([@palkan][])
|
26
|
+
|
27
|
+
- Add new TPS (tests per second) profiler. ([@palkan][])
|
28
|
+
|
29
|
+
- FactoryDefault: add Fabrication support. ([@palkan][])
|
30
|
+
|
31
|
+
- Drop support for **Ruby <2.7** and **Rails <6**.
|
32
|
+
|
33
|
+
- FactoryDefault: Add `#get_factory_default`. [[@john-h-k][]]
|
34
|
+
|
35
|
+
- Add variations information to FactorProf reports. ([@lHydra][])
|
36
|
+
|
37
|
+
Get info on traits/overrides used by running `FPROF=1 FPROF_VARS=1 <your test command>`.
|
38
|
+
|
39
|
+
- Add support for `report_duplicates` config option for `let_it_be` ([@lHydra][])
|
40
|
+
|
41
|
+
- Support latest Timecop patching `Process.clock_gettime`. ([@palkan][])
|
42
|
+
|
43
|
+
- Vernier: Add hooks configuration parameter. ([@lHydra][])
|
44
|
+
|
45
|
+
Now you can add more insights to the resulting report by adding event markers from Active Support Notifications.
|
46
|
+
To do this, specify the `TEST_VERNIER_HOOKS=rails` env var or set it through `Vernier` configuration:
|
47
|
+
|
48
|
+
```ruby
|
49
|
+
TestProf::Vernier.configure do |config|
|
50
|
+
config.hooks = :rails
|
51
|
+
end
|
52
|
+
```
|
53
|
+
|
54
|
+
- FactoryProf: Add threshold configuration parameter. ([@lHydra][])
|
55
|
+
|
56
|
+
Now you can ignore factories which total number of calls is less than the provided threshold. To do this, specify
|
57
|
+
the `FPROF_THRESHOLD=30` env var or set it through `FactoryProf` configuration:
|
58
|
+
|
59
|
+
```ruby
|
60
|
+
TestProf::FactoryProf.configure do |config|
|
61
|
+
config.threshold = 30
|
62
|
+
end
|
63
|
+
```
|
64
|
+
|
65
|
+
## 1.3.3 (2024-04-19)
|
66
|
+
|
67
|
+
- Fix MemProf bugs. ([@palkan][])
|
68
|
+
|
69
|
+
## 1.3.2 (2024-03-08) 🌷
|
70
|
+
|
71
|
+
- Add Minitest support for TagProf. ([@lioneldebauge][])
|
72
|
+
|
73
|
+
## 1.3.1 (2023-12-12)
|
74
|
+
|
75
|
+
- Add support for dumping FactoryProf results in JSON format. ([@uzushino][])
|
76
|
+
|
5
77
|
## 1.3.0 (2023-11-21)
|
6
78
|
|
7
79
|
- Add Vernier integration. ([@palkan][])
|
@@ -376,3 +448,9 @@ See [changelog](https://github.com/test-prof/test-prof/blob/v0.8.0/CHANGELOG.md)
|
|
376
448
|
[@peret]: https://github.com/peret
|
377
449
|
[@bf4]: https://github.com/bf4
|
378
450
|
[@Vankiru]: https://github.com/Vankiru
|
451
|
+
[@uzushino]: https://github.com/uzushino
|
452
|
+
[@lioneldebauge]: https://github.com/lioneldebauge
|
453
|
+
[@lHydra]: https://github.com/lHydra
|
454
|
+
[@john-h-k]: https://github.com/john-h-k
|
455
|
+
[@devinburnette]: https://github.com/devinburnette
|
456
|
+
[@elasticspoon]: https://github.com/elasticspoon
|
data/README.md
CHANGED
@@ -83,9 +83,9 @@ And that's it)
|
|
83
83
|
|
84
84
|
Supported Ruby versions:
|
85
85
|
|
86
|
-
- Ruby (MRI) >= 2.
|
86
|
+
- Ruby (MRI) >= 2.7.0 (**NOTE:** for Ruby 2.2 use TestProf < 0.7.0, Ruby 2.3 use TestProf ~> 0.7.0, Ruby 2.4 use TestProf <0.12.0, Ruby 2.5-2.6 use TestProf < 1.3)
|
87
87
|
|
88
|
-
- JRuby >= 9.
|
88
|
+
- JRuby >= 9.3.0
|
89
89
|
|
90
90
|
Supported RSpec version (for RSpec features only): >= 3.5.0 (for older RSpec versions use TestProf < 0.8.0).
|
91
91
|
|
@@ -3,6 +3,7 @@
|
|
3
3
|
require "test_prof/event_prof/minitest"
|
4
4
|
require "test_prof/factory_doctor/minitest"
|
5
5
|
require "test_prof/memory_prof/minitest"
|
6
|
+
require "test_prof/tag_prof/minitest"
|
6
7
|
|
7
8
|
module Minitest # :nodoc:
|
8
9
|
module TestProf # :nodoc:
|
@@ -16,6 +17,7 @@ module Minitest # :nodoc:
|
|
16
17
|
opts[:sample] = true if ENV["SAMPLE"] || ENV["SAMPLE_GROUPS"]
|
17
18
|
opts[:mem_prof_mode] = ENV["TEST_MEM_PROF"] if ENV["TEST_MEM_PROF"]
|
18
19
|
opts[:mem_prof_top_count] = ENV["TEST_MEM_PROF_COUNT"] if ENV["TEST_MEM_PROF_COUNT"]
|
20
|
+
opts[:tag_prof] = true if ENV["TAG_PROF"] == "type"
|
19
21
|
end
|
20
22
|
end
|
21
23
|
end
|
@@ -50,6 +52,7 @@ module Minitest # :nodoc:
|
|
50
52
|
reporter << TestProf::EventProfReporter.new(options[:io], options) if options[:event]
|
51
53
|
reporter << TestProf::FactoryDoctorReporter.new(options[:io], options) if options[:fdoc]
|
52
54
|
reporter << TestProf::MemoryProfReporter.new(options[:io], options) if options[:mem_prof_mode]
|
55
|
+
reporter << Minitest::TestProf::TagProfReporter.new(options[:io], options) if options[:tag_prof]
|
53
56
|
|
54
57
|
::TestProf::MinitestSample.call if options[:sample]
|
55
58
|
end
|
@@ -1,5 +1,10 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
if defined?(::ActiveRecord::Base)
|
4
|
+
require "test_prof/ext/active_record_refind"
|
5
|
+
using TestProf::Ext::ActiveRecordRefind
|
6
|
+
end
|
7
|
+
|
3
8
|
module TestProf
|
4
9
|
module AnyFixture
|
5
10
|
# Adds "global" `fixture`, `before_fixtures_reset` and `after_fixtures_reset` methods (through refinement)
|
@@ -9,7 +14,20 @@ module TestProf
|
|
9
14
|
# - Rails added `Kernel.prepend` in 6.1: https://github.com/rails/rails/commit/3124007bd674dcdc9c3b5c6b2964dfb7a1a0733c
|
10
15
|
refine ::Object do
|
11
16
|
def fixture(id, &block)
|
12
|
-
|
17
|
+
id = :"#{id}"
|
18
|
+
record = ::TestProf::AnyFixture.cached(id)
|
19
|
+
|
20
|
+
return ::TestProf::AnyFixture.register(id, &block) unless record
|
21
|
+
|
22
|
+
return record.refind if record.is_a?(::ActiveRecord::Base)
|
23
|
+
|
24
|
+
if record.respond_to?(:to_ary)
|
25
|
+
return record.map do |rec|
|
26
|
+
rec.is_a?(::ActiveRecord::Base) ? rec.refind : rec
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
record
|
13
31
|
end
|
14
32
|
|
15
33
|
def before_fixtures_reset(&block)
|
@@ -108,14 +108,18 @@ module TestProf
|
|
108
108
|
cached(id) do
|
109
109
|
raise "No fixture named #{id} has been registered" unless block_given?
|
110
110
|
|
111
|
+
next yield if @disabled
|
112
|
+
|
111
113
|
ActiveSupport::Notifications.subscribed(method(:subscriber), "sql.active_record") do
|
112
114
|
yield
|
113
115
|
end
|
114
116
|
end
|
115
117
|
end
|
116
118
|
|
117
|
-
def cached(id)
|
118
|
-
|
119
|
+
def cached(id, &block)
|
120
|
+
return (block_given? ? yield : nil) if @disabled
|
121
|
+
|
122
|
+
cache.fetch(id, &block)
|
119
123
|
end
|
120
124
|
|
121
125
|
# Create and register new SQL dump.
|
@@ -174,6 +178,14 @@ module TestProf
|
|
174
178
|
callbacks.clear
|
175
179
|
end
|
176
180
|
|
181
|
+
def disable!
|
182
|
+
@disabled = true
|
183
|
+
end
|
184
|
+
|
185
|
+
def enable!
|
186
|
+
@disabled = false
|
187
|
+
end
|
188
|
+
|
177
189
|
def before_fixtures_reset(&block)
|
178
190
|
callbacks[:before_fixtures_reset] << block
|
179
191
|
end
|
@@ -266,5 +278,7 @@ module TestProf
|
|
266
278
|
connection.disable_referential_integrity { yield }
|
267
279
|
end
|
268
280
|
end
|
281
|
+
|
282
|
+
enable!
|
269
283
|
end
|
270
284
|
end
|
@@ -8,44 +8,79 @@ module TestProf
|
|
8
8
|
POOL_ARGS = ((::ActiveRecord::VERSION::MAJOR > 6) ? [:writing] : []).freeze
|
9
9
|
|
10
10
|
class << self
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
log_pool_connection_error(pool, error)
|
18
|
-
nil
|
19
|
-
end
|
20
|
-
}
|
21
|
-
else
|
22
|
-
Array.wrap(::ActiveRecord::Base.connection)
|
11
|
+
if ::ActiveRecord::Base.connection.pool.respond_to?(:pin_connection!)
|
12
|
+
def begin_transaction
|
13
|
+
subscribe!
|
14
|
+
::ActiveRecord::Base.connection_handler.connection_pool_list(:writing).each do |pool|
|
15
|
+
pool.pin_connection!(true)
|
16
|
+
end
|
23
17
|
end
|
24
|
-
end
|
25
18
|
|
26
|
-
|
27
|
-
|
28
|
-
|
19
|
+
def rollback_transaction
|
20
|
+
::ActiveRecord::Base.connection_handler.connection_pool_list(:writing).each do |pool|
|
21
|
+
pool.unpin_connection!
|
22
|
+
end
|
23
|
+
unsubscribe!
|
24
|
+
end
|
29
25
|
|
30
|
-
|
31
|
-
|
32
|
-
|
26
|
+
def subscribe!
|
27
|
+
Thread.current[:before_all_connection_subscriber] = ActiveSupport::Notifications.subscribe("!connection.active_record") do |_, _, _, _, payload|
|
28
|
+
connection_name = payload[:connection_name] if payload.key?(:connection_name)
|
29
|
+
shard = payload[:shard] if payload.key?(:shard)
|
30
|
+
next unless connection_name
|
33
31
|
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
32
|
+
pool = ::ActiveRecord::Base.connection_handler.retrieve_connection_pool(connection_name, shard: shard)
|
33
|
+
next unless pool && pool.role == :writing
|
34
|
+
|
35
|
+
pool.pin_connection!(true)
|
36
|
+
end
|
38
37
|
end
|
39
|
-
end
|
40
38
|
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
39
|
+
def unsubscribe!
|
40
|
+
return unless Thread.current[:before_all_connection_subscriber]
|
41
|
+
ActiveSupport::Notifications.unsubscribe(Thread.current[:before_all_connection_subscriber])
|
42
|
+
Thread.current[:before_all_connection_subscriber] = nil
|
43
|
+
end
|
44
|
+
else
|
45
|
+
def all_connections
|
46
|
+
@all_connections ||= if ::ActiveRecord::Base.respond_to? :connects_to
|
47
|
+
::ActiveRecord::Base.connection_handler.connection_pool_list(*POOL_ARGS).filter_map { |pool|
|
48
|
+
begin
|
49
|
+
pool.connection
|
50
|
+
rescue *pool_connection_errors => error
|
51
|
+
log_pool_connection_error(pool, error)
|
52
|
+
nil
|
53
|
+
end
|
54
|
+
}
|
55
|
+
else
|
56
|
+
Array.wrap(::ActiveRecord::Base.connection)
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
def pool_connection_errors
|
61
|
+
@pool_connection_errors ||= []
|
62
|
+
end
|
63
|
+
|
64
|
+
def log_pool_connection_error(pool, error)
|
65
|
+
warn "Could not connect to pool #{pool.connection_class.name}. #{error.class}: #{error.message}"
|
66
|
+
end
|
67
|
+
|
68
|
+
def begin_transaction
|
69
|
+
@all_connections = nil
|
70
|
+
all_connections.each do |connection|
|
71
|
+
connection.begin_transaction(joinable: false)
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
def rollback_transaction
|
76
|
+
all_connections.each do |connection|
|
77
|
+
if connection.open_transactions.zero?
|
78
|
+
warn "!!! before_all transaction has been already rollbacked and " \
|
79
|
+
"could work incorrectly"
|
80
|
+
next
|
81
|
+
end
|
82
|
+
connection.rollback_transaction
|
47
83
|
end
|
48
|
-
connection.rollback_transaction
|
49
84
|
end
|
50
85
|
end
|
51
86
|
|
@@ -67,23 +102,23 @@ module TestProf
|
|
67
102
|
end
|
68
103
|
end
|
69
104
|
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
configure do |config|
|
74
|
-
# Make sure ActiveRecord uses locked thread.
|
75
|
-
# It only gets locked in `before` / `setup` hook,
|
76
|
-
# thus using thread in `before_all` (e.g. ActiveJob async adapter)
|
77
|
-
# might lead to leaking connections
|
78
|
-
config.before(:begin) do
|
79
|
-
next unless ::ActiveRecord::Base.connection.pool.respond_to?(:lock_thread=)
|
80
|
-
instance_variable_set("#{PREFIX_RESTORE_LOCK_THREAD}_orig_lock_thread", ::ActiveRecord::Base.connection.pool.instance_variable_get(:@lock_thread)) unless instance_variable_defined? "#{PREFIX_RESTORE_LOCK_THREAD}_orig_lock_thread"
|
81
|
-
::ActiveRecord::Base.connection.pool.lock_thread = true
|
82
|
-
end
|
105
|
+
unless ::ActiveRecord::Base.connection.pool.respond_to?(:pin_connection!)
|
106
|
+
# avoid instance variable collisions with cats
|
107
|
+
PREFIX_RESTORE_LOCK_THREAD = "@😺"
|
83
108
|
|
84
|
-
|
85
|
-
|
86
|
-
|
109
|
+
configure do |config|
|
110
|
+
# Make sure ActiveRecord uses locked thread.
|
111
|
+
# It only gets locked in `before` / `setup` hook,
|
112
|
+
# thus using thread in `before_all` (e.g. ActiveJob async adapter)
|
113
|
+
# might lead to leaking connections
|
114
|
+
config.before(:begin) do
|
115
|
+
instance_variable_set("#{PREFIX_RESTORE_LOCK_THREAD}_orig_lock_thread", ::ActiveRecord::Base.connection.pool.instance_variable_get(:@lock_thread)) unless instance_variable_defined? "#{PREFIX_RESTORE_LOCK_THREAD}_orig_lock_thread"
|
116
|
+
::ActiveRecord::Base.connection.pool.lock_thread = true
|
117
|
+
end
|
118
|
+
|
119
|
+
config.after(:rollback) do
|
120
|
+
::ActiveRecord::Base.connection.pool.lock_thread = instance_variable_get("#{PREFIX_RESTORE_LOCK_THREAD}_orig_lock_thread")
|
121
|
+
end
|
87
122
|
end
|
88
123
|
end
|
89
124
|
end
|
@@ -1,20 +1,11 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
def begin_transaction(*)
|
8
|
-
::Isolator.transactions_threshold += 1
|
9
|
-
super
|
10
|
-
end
|
3
|
+
TestProf::BeforeAll.configure do |config|
|
4
|
+
config.before(:begin) do
|
5
|
+
::Isolator.incr_thresholds!
|
6
|
+
end
|
11
7
|
|
12
|
-
|
13
|
-
|
14
|
-
::Isolator.transactions_threshold -= 1
|
15
|
-
end
|
16
|
-
end
|
8
|
+
config.after(:rollback) do
|
9
|
+
::Isolator.decr_thresholds!
|
17
10
|
end
|
18
11
|
end
|
19
|
-
|
20
|
-
TestProf::BeforeAll.singleton_class.prepend(TestProf::BeforeAll::Isolator)
|
data/lib/test_prof/before_all.rb
CHANGED
@@ -14,8 +14,26 @@ module TestProf
|
|
14
14
|
end
|
15
15
|
end
|
16
16
|
|
17
|
+
# Used in dry-run mode
|
18
|
+
class NoopAdapter
|
19
|
+
class << self
|
20
|
+
def begin_transaction(...)
|
21
|
+
end
|
22
|
+
|
23
|
+
def rollback_transaction(...)
|
24
|
+
end
|
25
|
+
|
26
|
+
def setup_fixtures(...)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
17
31
|
class << self
|
18
|
-
|
32
|
+
attr_writer :adapter
|
33
|
+
|
34
|
+
def adapter
|
35
|
+
@adapter ||= default_adapter
|
36
|
+
end
|
19
37
|
|
20
38
|
def begin_transaction(scope = nil, metadata = [])
|
21
39
|
raise AdapterMissing if adapter.nil?
|
@@ -47,6 +65,17 @@ module TestProf
|
|
47
65
|
def configure
|
48
66
|
yield config
|
49
67
|
end
|
68
|
+
|
69
|
+
private
|
70
|
+
|
71
|
+
def default_adapter
|
72
|
+
return NoopAdapter if TestProf.dry_run?
|
73
|
+
|
74
|
+
if defined?(::ActiveRecord::Base)
|
75
|
+
require "test_prof/before_all/adapters/active_record"
|
76
|
+
Adapters::ActiveRecord
|
77
|
+
end
|
78
|
+
end
|
50
79
|
end
|
51
80
|
|
52
81
|
class HookEntry # :nodoc:
|
@@ -66,7 +95,7 @@ module TestProf
|
|
66
95
|
private
|
67
96
|
|
68
97
|
def filters_apply?(metadata)
|
69
|
-
return true unless filters.
|
98
|
+
return true unless filters.is_a?(Hash) && TestProf.rspec?
|
70
99
|
|
71
100
|
::RSpec::Core::MetadataFilter.apply?(
|
72
101
|
:all?,
|
@@ -138,12 +167,6 @@ module TestProf
|
|
138
167
|
end
|
139
168
|
end
|
140
169
|
|
141
|
-
if defined?(::ActiveRecord::Base)
|
142
|
-
require "test_prof/before_all/adapters/active_record"
|
143
|
-
|
144
|
-
TestProf::BeforeAll.adapter = TestProf::BeforeAll::Adapters::ActiveRecord
|
145
|
-
end
|
146
|
-
|
147
170
|
if defined?(::Isolator)
|
148
171
|
require "test_prof/before_all/isolator"
|
149
172
|
end
|
@@ -3,7 +3,7 @@
|
|
3
3
|
module RuboCop
|
4
4
|
module Cop
|
5
5
|
module RSpec
|
6
|
-
class AggregateExamples < ::RuboCop::Cop::
|
6
|
+
class AggregateExamples < ::RuboCop::Cop::Base
|
7
7
|
# @example `its`
|
8
8
|
#
|
9
9
|
# # Supports regular `its` call with an attribute/method name,
|
@@ -64,7 +64,7 @@ module RuboCop
|
|
64
64
|
return super unless its?(example.send_node)
|
65
65
|
|
66
66
|
# First parameter to `its` is not metadata.
|
67
|
-
example.send_node.arguments[1
|
67
|
+
example.send_node.arguments[1..]
|
68
68
|
end
|
69
69
|
|
70
70
|
def its?(node)
|
@@ -5,7 +5,7 @@ require "test_prof/cops/rspec/language"
|
|
5
5
|
module RuboCop
|
6
6
|
module Cop
|
7
7
|
module RSpec
|
8
|
-
class AggregateExamples < ::RuboCop::Cop::
|
8
|
+
class AggregateExamples < ::RuboCop::Cop::Base
|
9
9
|
# When aggregated, the expectations will fail when not supposed to or
|
10
10
|
# have a risk of not failing when expected to. One example is
|
11
11
|
# `validate_presence_of :comment` as it leaves an empty comment after
|
@@ -108,7 +108,8 @@ module RuboCop
|
|
108
108
|
# expect(number).to be_odd
|
109
109
|
# end
|
110
110
|
#
|
111
|
-
class AggregateExamples < ::RuboCop::Cop::
|
111
|
+
class AggregateExamples < ::RuboCop::Cop::Base
|
112
|
+
extend AutoCorrector
|
112
113
|
include LineRangeHelpers
|
113
114
|
include MetadataHelpers
|
114
115
|
include NodeMatchers
|
@@ -123,29 +124,22 @@ module RuboCop
|
|
123
124
|
def on_block(node)
|
124
125
|
example_group_with_several_examples(node) do |all_examples|
|
125
126
|
example_clusters(all_examples).each do |_, examples|
|
126
|
-
examples
|
127
|
+
examples.drop(1).each do |example|
|
127
128
|
add_offense(example,
|
128
|
-
|
129
|
-
|
129
|
+
message: message_for(example, examples[0])) do |corrector|
|
130
|
+
clusters = example_clusters_for_autocorrect(example)
|
131
|
+
clusters.each do |metadata, examples|
|
132
|
+
range = range_for_replace(examples)
|
133
|
+
replacement = aggregated_example(examples, metadata)
|
134
|
+
corrector.replace(range, replacement)
|
135
|
+
examples.drop(1).map { |example| drop_example(corrector, example) }
|
136
|
+
end
|
137
|
+
end
|
130
138
|
end
|
131
139
|
end
|
132
140
|
end
|
133
141
|
end
|
134
142
|
|
135
|
-
def autocorrect(example_node)
|
136
|
-
clusters = example_clusters_for_autocorrect(example_node)
|
137
|
-
return if clusters.empty?
|
138
|
-
|
139
|
-
lambda do |corrector|
|
140
|
-
clusters.each do |metadata, examples|
|
141
|
-
range = range_for_replace(examples)
|
142
|
-
replacement = aggregated_example(examples, metadata)
|
143
|
-
corrector.replace(range, replacement)
|
144
|
-
examples[1..-1].map { |example| drop_example(corrector, example) }
|
145
|
-
end
|
146
|
-
end
|
147
|
-
end
|
148
|
-
|
149
143
|
private
|
150
144
|
|
151
145
|
# Clusters of examples in the same example group, on the same nesting
|
data/lib/test_prof/core.rb
CHANGED
@@ -6,6 +6,29 @@ require "logger"
|
|
6
6
|
require "test_prof/logging"
|
7
7
|
require "test_prof/utils"
|
8
8
|
|
9
|
+
# Add an alias for Process.clock_gettime "reserved" for TestProf
|
10
|
+
# (in case some other tool would like to patch it)
|
11
|
+
module ::Process
|
12
|
+
class << self
|
13
|
+
# Already patched by Timecop
|
14
|
+
if method_defined?(:clock_gettime_without_mock)
|
15
|
+
alias_method :clock_gettime_for_test_prof, :clock_gettime_without_mock
|
16
|
+
else
|
17
|
+
alias_method :clock_gettime_for_test_prof, :clock_gettime
|
18
|
+
|
19
|
+
def singleton_method_added(method_name)
|
20
|
+
return super unless method_name == :clock_gettime_without_mock
|
21
|
+
|
22
|
+
define_method(:clock_gettime_for_test_prof) { |*args| clock_gettime_without_mock(*args) }
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
# Main TestProf module
|
29
|
+
#
|
30
|
+
# Contains configuration and common methods
|
31
|
+
|
9
32
|
# Ruby applications tests profiling tools.
|
10
33
|
#
|
11
34
|
# Contains tools to analyze factories usage, integrate with Ruby profilers,
|
@@ -52,9 +75,13 @@ module TestProf
|
|
52
75
|
defined?(::Spring::Application) && (disabled.nil? || disabled.empty? || disabled == "0")
|
53
76
|
end
|
54
77
|
|
78
|
+
def dry_run?
|
79
|
+
rspec? && ::RSpec.configuration.dry_run?
|
80
|
+
end
|
81
|
+
|
55
82
|
# Returns the current process time
|
56
83
|
def now
|
57
|
-
Process.
|
84
|
+
Process.clock_gettime_for_test_prof(Process::CLOCK_MONOTONIC)
|
58
85
|
end
|
59
86
|
|
60
87
|
# Require gem and shows a custom
|
@@ -48,16 +48,9 @@ module TestProf
|
|
48
48
|
|
49
49
|
patch = Module.new do
|
50
50
|
mids.each do |mid|
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
tracker.track { super(*args, **kwargs, &block) }
|
55
|
-
end
|
56
|
-
else
|
57
|
-
define_method(mid) do |*args, &block|
|
58
|
-
next super(*args, &block) unless guard.nil? || instance_exec(*args, &guard)
|
59
|
-
tracker.track { super(*args, &block) }
|
60
|
-
end
|
51
|
+
define_method(mid) do |*args, **kwargs, &block|
|
52
|
+
next super(*args, **kwargs, &block) unless guard.nil? || instance_exec(*args, **kwargs, &guard)
|
53
|
+
tracker.track { super(*args, **kwargs, &block) }
|
61
54
|
end
|
62
55
|
end
|
63
56
|
end
|