test-prof 0.7.5 → 0.8.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
|