test-prof 0.7.5 → 0.8.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/CHANGELOG.md +20 -2
- data/README.md +5 -3
- data/lib/minitest/base_reporter.rb +18 -12
- data/lib/minitest/test_prof_plugin.rb +8 -8
- data/lib/test_prof.rb +3 -3
- data/lib/test_prof/any_fixture.rb +3 -3
- data/lib/test_prof/before_all.rb +9 -0
- data/lib/test_prof/before_all/adapters/active_record.rb +12 -0
- data/lib/test_prof/before_all/isolator.rb +18 -0
- data/lib/test_prof/cops/rspec/aggregate_failures.rb +6 -6
- data/lib/test_prof/event_prof.rb +6 -6
- data/lib/test_prof/event_prof/custom_events/factory_create.rb +1 -1
- data/lib/test_prof/event_prof/custom_events/sidekiq_inline.rb +2 -2
- data/lib/test_prof/event_prof/custom_events/sidekiq_jobs.rb +2 -2
- data/lib/test_prof/event_prof/instrumentations/active_support.rb +1 -1
- data/lib/test_prof/event_prof/minitest.rb +4 -4
- data/lib/test_prof/event_prof/rspec.rb +4 -11
- data/lib/test_prof/factory_bot.rb +1 -1
- data/lib/test_prof/factory_default.rb +1 -1
- data/lib/test_prof/factory_doctor.rb +2 -2
- data/lib/test_prof/factory_doctor/minitest.rb +4 -4
- data/lib/test_prof/factory_doctor/rspec.rb +7 -10
- data/lib/test_prof/factory_prof.rb +6 -6
- data/lib/test_prof/factory_prof/factory_builders/fabrication.rb +1 -1
- data/lib/test_prof/factory_prof/printers/flamegraph.rb +1 -1
- data/lib/test_prof/recipes/logging.rb +86 -21
- data/lib/test_prof/recipes/minitest/before_all.rb +3 -2
- data/lib/test_prof/recipes/minitest/sample.rb +5 -5
- data/lib/test_prof/recipes/rspec/any_fixture.rb +3 -1
- data/lib/test_prof/recipes/rspec/before_all.rb +12 -3
- data/lib/test_prof/recipes/rspec/factory_all_stub.rb +5 -1
- data/lib/test_prof/recipes/rspec/let_it_be.rb +3 -13
- data/lib/test_prof/rspec_dissect.rb +13 -19
- data/lib/test_prof/rspec_dissect/rspec.rb +2 -6
- data/lib/test_prof/rspec_stamp.rb +14 -14
- data/lib/test_prof/rspec_stamp/parser.rb +1 -1
- data/lib/test_prof/rspec_stamp/rspec.rb +1 -1
- data/lib/test_prof/ruby_prof.rb +32 -24
- data/lib/test_prof/ruby_prof/rspec.rb +2 -6
- data/lib/test_prof/stack_prof.rb +23 -15
- data/lib/test_prof/stack_prof/rspec.rb +5 -6
- data/lib/test_prof/tag_prof/printers/simple.rb +4 -4
- data/lib/test_prof/tag_prof/result.rb +3 -3
- data/lib/test_prof/tag_prof/rspec.rb +9 -14
- data/lib/test_prof/utils/html_builder.rb +1 -1
- data/lib/test_prof/utils/sized_ordered_set.rb +1 -1
- data/lib/test_prof/version.rb +1 -1
- metadata +37 -9
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 65bd3447c63c3e7c037707ebd0f637831ccf0c98af1b0b3d9bf0a6fa72c56b11
|
4
|
+
data.tar.gz: d6af1b43e6924c67ef4c2297602ef641377584f3282eafc236e48eb951e04b68
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 2eae07fcbce70eb7598b92fc578530ed5e20edfb3d7752c672740d44aa13f5d925005500aa26e83ce004c0b2ba128b0091362c39771b67e12d352360aacc2081
|
7
|
+
data.tar.gz: 213858acbdaa8d5e2e6e1fcdd99ca952a044949d23846f631a34513d379ce583013c13ed76c0303c8bd8fec777f44b99bf992e8937598d22bf4110cedb408eb6
|
data/CHANGELOG.md
CHANGED
@@ -2,6 +2,24 @@
|
|
2
2
|
|
3
3
|
## master
|
4
4
|
|
5
|
+
## 0.8.0 (2019-04-12) 🚀
|
6
|
+
|
7
|
+
- **Ruby 2.4+ is requiered** ([@palkan][])
|
8
|
+
|
9
|
+
- **RSpec 3.5+ is requiered for RSpec features** ([@palkan][])
|
10
|
+
|
11
|
+
- Make `before_all` compatible with [`isolator`](https://github.com/palkan/isolator). ([@palkan][])
|
12
|
+
|
13
|
+
- Add `with_logging` and `with_ar_logging` helpers to logging recipe. ([@palkan][])
|
14
|
+
|
15
|
+
- Make `before_all` for Active Record `lock_thread` aware. ([@palkan][])
|
16
|
+
|
17
|
+
`before_all` can went crazy if you open multiple connections within it
|
18
|
+
(since it tracks the number of open transactions).
|
19
|
+
Rails 5+ `lock_thread` feature only locks the connection thread in
|
20
|
+
`before`/`setup` hook thus making it possible to have multiple connections/transactions
|
21
|
+
in `before_all` (e.g. performing jobs with Active Job async adapter).
|
22
|
+
|
5
23
|
## 0.7.5 (2019-02-22)
|
6
24
|
|
7
25
|
- Make `let_it_be` and `before_all` work with `include_context`. ([@palkan][])
|
@@ -58,7 +76,7 @@ Add ability to specify custom exclusions through `config.custom_exclusions`, e.g
|
|
58
76
|
|
59
77
|
```ruby
|
60
78
|
TestProf::RubyProf.configure do |config|
|
61
|
-
config.custom_exclusions = {
|
79
|
+
config.custom_exclusions = {User => %i[save save!]}
|
62
80
|
end
|
63
81
|
```
|
64
82
|
|
@@ -161,7 +179,7 @@ LOG=all rspec
|
|
161
179
|
Or per example (group):
|
162
180
|
|
163
181
|
```ruby
|
164
|
-
it
|
182
|
+
it "does smth weird", :log do
|
165
183
|
# ...
|
166
184
|
end
|
167
185
|
```
|
data/README.md
CHANGED
@@ -33,9 +33,11 @@ Of course, we have some [solutions](https://test-prof.evilmartians.io/#/?id=reci
|
|
33
33
|
|
34
34
|
Supported Ruby versions:
|
35
35
|
|
36
|
-
- Ruby (MRI) >= 2.
|
36
|
+
- Ruby (MRI) >= 2.4.0 (**NOTE:** for Ruby 2.2 use TestProf < 0.7.0 or Ruby 2.3 use TestProf ~> 0.7.0)
|
37
37
|
|
38
|
-
- JRuby >= 9.1.0.0
|
38
|
+
- JRuby >= 9.1.0.0 (**NOTE:** refinements-dependent features might require 9.2.7+)
|
39
|
+
|
40
|
+
Supported RSpec version (for RSpec features only): >= 3.5.0 (for older RSpec versions use TestProf < 0.8.0).
|
39
41
|
|
40
42
|
<a href="https://evilmartians.com/">
|
41
43
|
<img src="https://evilmartians.com/badges/sponsored-by-evil-martians.svg" alt="Sponsored by Evil Martians" width="236" height="54"></a>
|
@@ -62,7 +64,7 @@ Add `test-prof` gem to your application:
|
|
62
64
|
|
63
65
|
```ruby
|
64
66
|
group :test do
|
65
|
-
gem
|
67
|
+
gem "test-prof"
|
66
68
|
end
|
67
69
|
```
|
68
70
|
|
@@ -1,7 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require
|
4
|
-
require
|
3
|
+
require "minitest"
|
4
|
+
require "test_prof/logging"
|
5
5
|
|
6
6
|
module Minitest
|
7
7
|
module TestProf
|
@@ -15,17 +15,23 @@ module Minitest
|
|
15
15
|
inject_to_minitest_reporters if defined? Minitest::Reporters
|
16
16
|
end
|
17
17
|
|
18
|
-
def start
|
18
|
+
def start
|
19
|
+
end
|
19
20
|
|
20
|
-
def prerecord(group, example)
|
21
|
+
def prerecord(group, example)
|
22
|
+
end
|
21
23
|
|
22
|
-
def before_test(test)
|
24
|
+
def before_test(test)
|
25
|
+
end
|
23
26
|
|
24
|
-
def record(*)
|
27
|
+
def record(*)
|
28
|
+
end
|
25
29
|
|
26
|
-
def after_test(test)
|
30
|
+
def after_test(test)
|
31
|
+
end
|
27
32
|
|
28
|
-
def report
|
33
|
+
def report
|
34
|
+
end
|
29
35
|
|
30
36
|
private
|
31
37
|
|
@@ -33,22 +39,22 @@ module Minitest
|
|
33
39
|
# Minitest::Result (>= 5.11) has `source_location` method
|
34
40
|
return group.source_location if group.respond_to?(:source_location)
|
35
41
|
if group.is_a? Class
|
36
|
-
suite = group.public_instance_methods.select { |mtd| mtd.to_s.match
|
42
|
+
suite = group.public_instance_methods.select { |mtd| mtd.to_s.match(/^test_/) }
|
37
43
|
name = suite.find { |mtd| mtd.to_s == example }
|
38
44
|
group.instance_method(name).source_location
|
39
45
|
else
|
40
|
-
suite = group.methods.select { |mtd| mtd.to_s.match
|
46
|
+
suite = group.methods.select { |mtd| mtd.to_s.match(/^test_/) }
|
41
47
|
name = suite.find { |mtd| mtd.to_s == group.name }
|
42
48
|
group.method(name).source_location
|
43
49
|
end
|
44
50
|
end
|
45
51
|
|
46
52
|
def location_with_line_number(group, example = nil)
|
47
|
-
File.expand_path(location(group, example).join(
|
53
|
+
File.expand_path(location(group, example).join(":")).gsub(Dir.getwd, ".")
|
48
54
|
end
|
49
55
|
|
50
56
|
def location_without_line_number(group, example = nil)
|
51
|
-
File.expand_path(location(group, example).first).gsub(Dir.getwd,
|
57
|
+
File.expand_path(location(group, example).first).gsub(Dir.getwd, ".")
|
52
58
|
end
|
53
59
|
|
54
60
|
def inject_to_minitest_reporters
|
@@ -1,17 +1,17 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require
|
4
|
-
require
|
3
|
+
require "test_prof/event_prof/minitest"
|
4
|
+
require "test_prof/factory_doctor/minitest"
|
5
5
|
|
6
6
|
module Minitest # :nodoc:
|
7
7
|
module TestProf # :nodoc:
|
8
8
|
def self.configure_options(options = {})
|
9
9
|
options.tap do |opts|
|
10
|
-
opts[:event] = ENV[
|
11
|
-
opts[:rank_by] = ENV[
|
12
|
-
opts[:top_count] = ENV[
|
13
|
-
opts[:per_example] = true if ENV[
|
14
|
-
opts[:fdoc] = true if ENV[
|
10
|
+
opts[:event] = ENV["EVENT_PROF"] if ENV["EVENT_PROF"]
|
11
|
+
opts[:rank_by] = ENV["EVENT_PROF_RANK"].to_sym if ENV["EVENT_PROF_RANK"]
|
12
|
+
opts[:top_count] = ENV["EVENT_PROF_TOP"].to_i if ENV["EVENT_PROF_TOP"]
|
13
|
+
opts[:per_example] = true if ENV["EVENT_PROF_EXAMPLES"]
|
14
|
+
opts[:fdoc] = true if ENV["FDOC"]
|
15
15
|
end
|
16
16
|
end
|
17
17
|
end
|
@@ -29,7 +29,7 @@ module Minitest # :nodoc:
|
|
29
29
|
opts.on "--event-prof-per-example", TrueClass, "Includes examples metrics to results" do |flag|
|
30
30
|
options[:per_example] = flag
|
31
31
|
end
|
32
|
-
opts.on "--factory-doctor", TrueClass,
|
32
|
+
opts.on "--factory-doctor", TrueClass, "Enable Factory Doctor for your examples" do |flag|
|
33
33
|
options[:fdoc] = flag
|
34
34
|
end
|
35
35
|
end
|
data/lib/test_prof.rb
CHANGED
@@ -114,13 +114,13 @@ module TestProf
|
|
114
114
|
def with_timestamps(path)
|
115
115
|
return path unless config.timestamps?
|
116
116
|
timestamps = "-#{now.to_i}"
|
117
|
-
"#{path.sub(/\.\w+$/,
|
117
|
+
"#{path.sub(/\.\w+$/, "")}#{timestamps}#{::File.extname(path)}"
|
118
118
|
end
|
119
119
|
|
120
120
|
def with_report_suffix(path)
|
121
121
|
return path if config.report_suffix.nil?
|
122
122
|
|
123
|
-
"#{path.sub(/\.\w+$/,
|
123
|
+
"#{path.sub(/\.\w+$/, "")}-#{config.report_suffix}#{::File.extname(path)}"
|
124
124
|
end
|
125
125
|
|
126
126
|
def notify_spring_detected
|
@@ -147,7 +147,7 @@ module TestProf
|
|
147
147
|
@color = true
|
148
148
|
@output_dir = "tmp/test_prof"
|
149
149
|
@timestamps = false
|
150
|
-
@report_suffix = ENV[
|
150
|
+
@report_suffix = ENV["TEST_PROF_REPORT"]
|
151
151
|
end
|
152
152
|
|
153
153
|
def color?
|
@@ -27,7 +27,7 @@ module TestProf
|
|
27
27
|
|
28
28
|
ts = TestProf.now
|
29
29
|
store[key] = yield
|
30
|
-
stats[key] = {
|
30
|
+
stats[key] = {time: TestProf.now - ts, hit: 0}
|
31
31
|
store[key]
|
32
32
|
end
|
33
33
|
|
@@ -91,7 +91,7 @@ module TestProf
|
|
91
91
|
|
92
92
|
msgs << format(
|
93
93
|
"%#{first_column}s %12s %9s %12s",
|
94
|
-
|
94
|
+
"key", "build time", "hit count", "saved time"
|
95
95
|
)
|
96
96
|
|
97
97
|
msgs << ""
|
@@ -144,6 +144,6 @@ module TestProf
|
|
144
144
|
end
|
145
145
|
end
|
146
146
|
|
147
|
-
self.reporting_enabled = ENV[
|
147
|
+
self.reporting_enabled = ENV["ANYFIXTURE_REPORT"] == "1"
|
148
148
|
end
|
149
149
|
end
|
data/lib/test_prof/before_all.rb
CHANGED
@@ -18,6 +18,11 @@ module TestProf
|
|
18
18
|
def begin_transaction
|
19
19
|
raise AdapterMissing if adapter.nil?
|
20
20
|
adapter.begin_transaction
|
21
|
+
yield
|
22
|
+
end
|
23
|
+
|
24
|
+
def within_transaction
|
25
|
+
yield
|
21
26
|
end
|
22
27
|
|
23
28
|
def rollback_transaction
|
@@ -33,3 +38,7 @@ if defined?(::ActiveRecord::Base)
|
|
33
38
|
|
34
39
|
TestProf::BeforeAll.adapter = TestProf::BeforeAll::Adapters::ActiveRecord
|
35
40
|
end
|
41
|
+
|
42
|
+
if defined?(::Isolator)
|
43
|
+
require "test_prof/before_all/isolator"
|
44
|
+
end
|
@@ -12,6 +12,7 @@ module TestProf
|
|
12
12
|
module ActiveRecord
|
13
13
|
class << self
|
14
14
|
def begin_transaction
|
15
|
+
lock_thread!
|
15
16
|
::ActiveRecord::Base.connection.begin_transaction(joinable: false)
|
16
17
|
end
|
17
18
|
|
@@ -23,6 +24,17 @@ module TestProf
|
|
23
24
|
end
|
24
25
|
::ActiveRecord::Base.connection.rollback_transaction
|
25
26
|
end
|
27
|
+
|
28
|
+
private
|
29
|
+
|
30
|
+
# Make sure ActiveRecord uses locked thread.
|
31
|
+
# It only gets locked in `before` / `setup` hook,
|
32
|
+
# thus using thread in `before_all` (e.g. ActiveJob async adapter)
|
33
|
+
# might lead to leaking connections
|
34
|
+
def lock_thread!
|
35
|
+
return unless ::ActiveRecord::Base.connection.pool.respond_to?(:lock_thread=)
|
36
|
+
::ActiveRecord::Base.connection.pool.lock_thread = true
|
37
|
+
end
|
26
38
|
end
|
27
39
|
end
|
28
40
|
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module TestProf
|
4
|
+
module BeforeAll
|
5
|
+
# Disable Isolator within before_all blocks
|
6
|
+
module Isolator
|
7
|
+
def begin_transaction(*)
|
8
|
+
::Isolator.disable { super }
|
9
|
+
end
|
10
|
+
|
11
|
+
def within_transaction(*)
|
12
|
+
::Isolator.disable { super }
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
TestProf::BeforeAll.singleton_class.prepend(TestProf::BeforeAll::Isolator)
|
@@ -1,7 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require
|
4
|
-
require
|
3
|
+
require "rubocop"
|
4
|
+
require "test_prof/utils"
|
5
5
|
|
6
6
|
module RuboCop
|
7
7
|
module Cop
|
@@ -38,7 +38,7 @@ module RuboCop
|
|
38
38
|
class << self
|
39
39
|
def supported?
|
40
40
|
return @supported if instance_variable_defined?(:@supported)
|
41
|
-
@supported = TestProf::Utils.verify_gem_version(
|
41
|
+
@supported = TestProf::Utils.verify_gem_version("rubocop", at_least: "0.51.0")
|
42
42
|
|
43
43
|
unless @supported
|
44
44
|
warn "RSpec/AggregateFailures cop requires RuboCop >= 0.51.0. Skipping"
|
@@ -62,7 +62,7 @@ module RuboCop
|
|
62
62
|
add_offense(
|
63
63
|
node,
|
64
64
|
location: :expression,
|
65
|
-
message:
|
65
|
+
message: "Use :aggregate_failures instead of several one-liners."
|
66
66
|
)
|
67
67
|
end
|
68
68
|
|
@@ -140,7 +140,7 @@ module RuboCop
|
|
140
140
|
%(#{method_name} "works", :aggregate_failures do)
|
141
141
|
end
|
142
142
|
|
143
|
-
def body_from(node, base_indent =
|
143
|
+
def body_from(node, base_indent = "")
|
144
144
|
method, _args, body = *node
|
145
145
|
body_source = method.method_name == :its ? body_from_its(method, body) : body.source
|
146
146
|
"#{base_indent}#{indent}#{body_source}"
|
@@ -162,7 +162,7 @@ module RuboCop
|
|
162
162
|
end
|
163
163
|
|
164
164
|
def indent
|
165
|
-
@indent ||= " " * (config.for_cop(
|
165
|
+
@indent ||= " " * (config.for_cop("IndentationWidth")["Width"] || 2)
|
166
166
|
end
|
167
167
|
end
|
168
168
|
end
|
data/lib/test_prof/event_prof.rb
CHANGED
@@ -31,19 +31,19 @@ module TestProf
|
|
31
31
|
class Configuration
|
32
32
|
# Map of supported instrumenters
|
33
33
|
INSTRUMENTERS = {
|
34
|
-
active_support:
|
34
|
+
active_support: "ActiveSupport"
|
35
35
|
}.freeze
|
36
36
|
|
37
37
|
attr_accessor :instrumenter, :top_count, :per_example,
|
38
38
|
:rank_by, :event
|
39
39
|
|
40
40
|
def initialize
|
41
|
-
@event = ENV[
|
41
|
+
@event = ENV["EVENT_PROF"]
|
42
42
|
@instrumenter = :active_support
|
43
|
-
@top_count = (ENV[
|
44
|
-
@per_example = ENV[
|
45
|
-
@rank_by = (ENV[
|
46
|
-
@stamp = ENV[
|
43
|
+
@top_count = (ENV["EVENT_PROF_TOP"] || 5).to_i
|
44
|
+
@per_example = ENV["EVENT_PROF_EXAMPLES"] == "1"
|
45
|
+
@rank_by = (ENV["EVENT_PROF_RANK"] || :time).to_sym
|
46
|
+
@stamp = ENV["EVENT_PROF_STAMP"]
|
47
47
|
|
48
48
|
RSpecStamp.config.tags = @stamp if stamp?
|
49
49
|
end
|
@@ -22,7 +22,7 @@ module TestProf::EventProf::CustomEvents
|
|
22
22
|
res =
|
23
23
|
if @depth == 1
|
24
24
|
ActiveSupport::Notifications.instrument(
|
25
|
-
|
25
|
+
"sidekiq.inline"
|
26
26
|
) { yield }
|
27
27
|
else
|
28
28
|
yield
|
@@ -38,7 +38,7 @@ end
|
|
38
38
|
|
39
39
|
TestProf::EventProf::CustomEvents.register("sidekiq.inline") do
|
40
40
|
if TestProf.require(
|
41
|
-
|
41
|
+
"sidekiq/testing",
|
42
42
|
<<~MSG
|
43
43
|
Failed to load Sidekiq.
|
44
44
|
|
@@ -16,7 +16,7 @@ module TestProf::EventProf::CustomEvents
|
|
16
16
|
|
17
17
|
def track
|
18
18
|
ActiveSupport::Notifications.instrument(
|
19
|
-
|
19
|
+
"sidekiq.jobs"
|
20
20
|
) { yield }
|
21
21
|
end
|
22
22
|
end
|
@@ -25,7 +25,7 @@ end
|
|
25
25
|
|
26
26
|
TestProf::EventProf::CustomEvents.register("sidekiq.jobs") do
|
27
27
|
if TestProf.require(
|
28
|
-
|
28
|
+
"sidekiq/testing",
|
29
29
|
<<~MSG
|
30
30
|
Failed to load Sidekiq.
|
31
31
|
|
@@ -6,7 +6,7 @@ module TestProf::EventProf
|
|
6
6
|
module ActiveSupport
|
7
7
|
class << self
|
8
8
|
def subscribe(event)
|
9
|
-
raise ArgumentError,
|
9
|
+
raise ArgumentError, "Block is required!" unless block_given?
|
10
10
|
|
11
11
|
::ActiveSupport::Notifications.subscribe(event) do |_event, start, finish, *_args|
|
12
12
|
yield (finish - start)
|
@@ -1,7 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require
|
4
|
-
require
|
3
|
+
require "minitest/base_reporter"
|
4
|
+
require "minitest/event_prof_formatter"
|
5
5
|
|
6
6
|
module Minitest
|
7
7
|
module TestProf
|
@@ -10,7 +10,7 @@ module Minitest
|
|
10
10
|
super
|
11
11
|
@profiler = configure_profiler(options)
|
12
12
|
|
13
|
-
log :info, "EventProf enabled (#{@profiler.events.join(
|
13
|
+
log :info, "EventProf enabled (#{@profiler.events.join(", ")})"
|
14
14
|
|
15
15
|
@formatter = EventProfFormatter.new(@profiler)
|
16
16
|
@current_group = nil
|
@@ -45,7 +45,7 @@ module Minitest
|
|
45
45
|
end
|
46
46
|
|
47
47
|
@current_example = {
|
48
|
-
name: example.gsub(/^test_(?:\d+_)?/,
|
48
|
+
name: example.gsub(/^test_(?:\d+_)?/, ""),
|
49
49
|
location: location_with_line_number(group, example)
|
50
50
|
}
|
51
51
|
|