test-prof 0.1.0.beta1
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 +7 -0
- data/CHANGELOG.md +7 -0
- data/LICENSE.txt +21 -0
- data/README.md +103 -0
- data/assets/flamegraph.demo.html +173 -0
- data/assets/flamegraph.template.html +196 -0
- data/assets/src/d3-tip.js +352 -0
- data/assets/src/d3-tip.min.js +1 -0
- data/assets/src/d3.flameGraph.css +92 -0
- data/assets/src/d3.flameGraph.js +459 -0
- data/assets/src/d3.flameGraph.min.css +1 -0
- data/assets/src/d3.flameGraph.min.js +1 -0
- data/assets/src/d3.v4.min.js +8 -0
- data/guides/any_fixture.md +60 -0
- data/guides/before_all.md +98 -0
- data/guides/event_prof.md +97 -0
- data/guides/factory_doctor.md +64 -0
- data/guides/factory_prof.md +85 -0
- data/guides/rspec_stamp.md +53 -0
- data/guides/rubocop.md +48 -0
- data/guides/ruby_prof.md +61 -0
- data/guides/stack_prof.md +43 -0
- data/lib/test-prof.rb +3 -0
- data/lib/test_prof/any_fixture.rb +67 -0
- data/lib/test_prof/cops/rspec/aggregate_failures.rb +140 -0
- data/lib/test_prof/event_prof/custom_events/factory_create.rb +51 -0
- data/lib/test_prof/event_prof/custom_events/sidekiq_inline.rb +48 -0
- data/lib/test_prof/event_prof/custom_events/sidekiq_jobs.rb +38 -0
- data/lib/test_prof/event_prof/custom_events.rb +5 -0
- data/lib/test_prof/event_prof/instrumentations/active_support.rb +16 -0
- data/lib/test_prof/event_prof/minitest.rb +3 -0
- data/lib/test_prof/event_prof/rspec.rb +94 -0
- data/lib/test_prof/event_prof.rb +177 -0
- data/lib/test_prof/ext/float_duration.rb +14 -0
- data/lib/test_prof/factory_doctor/factory_girl_patch.rb +12 -0
- data/lib/test_prof/factory_doctor/minitest.rb +3 -0
- data/lib/test_prof/factory_doctor/rspec.rb +96 -0
- data/lib/test_prof/factory_doctor.rb +133 -0
- data/lib/test_prof/factory_prof/factory_girl_patch.rb +12 -0
- data/lib/test_prof/factory_prof/printers/flamegraph.rb +71 -0
- data/lib/test_prof/factory_prof/printers/simple.rb +28 -0
- data/lib/test_prof/factory_prof.rb +140 -0
- data/lib/test_prof/logging.rb +25 -0
- data/lib/test_prof/recipes/rspec/any_fixture.rb +21 -0
- data/lib/test_prof/recipes/rspec/before_all.rb +23 -0
- data/lib/test_prof/rspec_stamp/parser.rb +103 -0
- data/lib/test_prof/rspec_stamp/rspec.rb +91 -0
- data/lib/test_prof/rspec_stamp.rb +135 -0
- data/lib/test_prof/rubocop.rb +3 -0
- data/lib/test_prof/ruby_prof/rspec.rb +13 -0
- data/lib/test_prof/ruby_prof.rb +194 -0
- data/lib/test_prof/stack_prof/rspec.rb +13 -0
- data/lib/test_prof/stack_prof.rb +120 -0
- data/lib/test_prof/version.rb +5 -0
- data/lib/test_prof.rb +108 -0
- metadata +227 -0
@@ -0,0 +1,13 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Shared example for RSpec to profile specific examples with StackProf
|
4
|
+
RSpec.shared_context "stackprof", sprof: true do
|
5
|
+
prepend_before do
|
6
|
+
@stack_prof_report = TestProf::StackProf.profile
|
7
|
+
end
|
8
|
+
|
9
|
+
append_after do |ex|
|
10
|
+
next unless @stack_prof_report
|
11
|
+
TestProf::StackProf.dump ex.full_description.parameterize
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,120 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module TestProf
|
4
|
+
# StackProf wrapper.
|
5
|
+
#
|
6
|
+
# Has 2 modes: global and per-example.
|
7
|
+
#
|
8
|
+
# Example:
|
9
|
+
#
|
10
|
+
# # To activate global profiling you can use env variable
|
11
|
+
# TEST_STACK_PROF=1 rspec ...
|
12
|
+
#
|
13
|
+
# # or in your code
|
14
|
+
# TestProf::StackProf.run
|
15
|
+
#
|
16
|
+
# To profile a specific examples add :sprof tag to it:
|
17
|
+
#
|
18
|
+
# it "is doing heavy stuff", :sprof do
|
19
|
+
# ...
|
20
|
+
# end
|
21
|
+
#
|
22
|
+
module StackProf
|
23
|
+
# StackProf configuration
|
24
|
+
class Configuration
|
25
|
+
attr_accessor :mode, :interval, :raw
|
26
|
+
|
27
|
+
def initialize
|
28
|
+
@mode = :wall
|
29
|
+
@raw = false
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
class << self
|
34
|
+
include Logging
|
35
|
+
|
36
|
+
def config
|
37
|
+
@config ||= Configuration.new
|
38
|
+
end
|
39
|
+
|
40
|
+
def configure
|
41
|
+
yield config
|
42
|
+
end
|
43
|
+
|
44
|
+
# Run StackProf and automatically dump
|
45
|
+
# a report when the process exits.
|
46
|
+
#
|
47
|
+
# Use this method to profile the whole run.
|
48
|
+
def run
|
49
|
+
return unless profile
|
50
|
+
|
51
|
+
@locked = true
|
52
|
+
|
53
|
+
log :info, "StackProf enabled"
|
54
|
+
|
55
|
+
at_exit { dump("total") }
|
56
|
+
end
|
57
|
+
|
58
|
+
def profile(name = nil)
|
59
|
+
return if locked?
|
60
|
+
return unless init_stack_prof
|
61
|
+
|
62
|
+
options = {
|
63
|
+
mode: config.mode,
|
64
|
+
raw: config.raw
|
65
|
+
}
|
66
|
+
|
67
|
+
options[:interval] = config.interval if config.interval
|
68
|
+
|
69
|
+
if block_given?
|
70
|
+
options[:out] = build_path(name)
|
71
|
+
::StackProf.run(options) { yield }
|
72
|
+
else
|
73
|
+
::StackProf.start(options)
|
74
|
+
end
|
75
|
+
true
|
76
|
+
end
|
77
|
+
|
78
|
+
def dump(name)
|
79
|
+
::StackProf.stop
|
80
|
+
|
81
|
+
path = build_path(name)
|
82
|
+
|
83
|
+
::StackProf.results(path)
|
84
|
+
|
85
|
+
log :info, "StackProf report generated: #{path}"
|
86
|
+
end
|
87
|
+
|
88
|
+
private
|
89
|
+
|
90
|
+
def build_path(name)
|
91
|
+
TestProf.artefact_path(
|
92
|
+
"stack-prof-report-#{config.mode}-#{name}.dump"
|
93
|
+
)
|
94
|
+
end
|
95
|
+
|
96
|
+
def locked?
|
97
|
+
@locked == true
|
98
|
+
end
|
99
|
+
|
100
|
+
def init_stack_prof
|
101
|
+
return @initialized if instance_variable_defined?(:@initialized)
|
102
|
+
@initialized = TestProf.require(
|
103
|
+
'stackprof',
|
104
|
+
<<~MSG
|
105
|
+
Please, install 'stackprof' first:
|
106
|
+
# Gemfile
|
107
|
+
gem 'stackprof', require: false
|
108
|
+
MSG
|
109
|
+
)
|
110
|
+
end
|
111
|
+
end
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
115
|
+
require "test_prof/stack_prof/rspec" if defined?(RSpec)
|
116
|
+
|
117
|
+
# Hook to run StackProf globally
|
118
|
+
TestProf.activate('TEST_STACK_PROF') do
|
119
|
+
TestProf::StackProf.run
|
120
|
+
end
|
data/lib/test_prof.rb
ADDED
@@ -0,0 +1,108 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "test_prof/version"
|
4
|
+
require "test_prof/logging"
|
5
|
+
|
6
|
+
# Ruby applications tests profiling tools.
|
7
|
+
#
|
8
|
+
# Contains tools to anylyze factories usage, integrate with Ruby profilers,
|
9
|
+
# profile your examples using ActiveSupport notifications (if any) and
|
10
|
+
# statically analyze your code with custom Rubocop cops.
|
11
|
+
#
|
12
|
+
# Example usage:
|
13
|
+
#
|
14
|
+
# require 'test_prof'
|
15
|
+
#
|
16
|
+
# # Activate a tool by providing environment variable, e.g.
|
17
|
+
# TEST_RUBY_PROF=1 rspec ...
|
18
|
+
#
|
19
|
+
# # or manually in your code
|
20
|
+
# TestProf::RubyProf.run
|
21
|
+
#
|
22
|
+
# See other modules for more examples.
|
23
|
+
module TestProf
|
24
|
+
class << self
|
25
|
+
include Logging
|
26
|
+
|
27
|
+
def config
|
28
|
+
@config ||= Configuration.new
|
29
|
+
end
|
30
|
+
|
31
|
+
def configure
|
32
|
+
yield config
|
33
|
+
end
|
34
|
+
|
35
|
+
# Require gem and shows a custom
|
36
|
+
# message if it fails to load
|
37
|
+
def require(gem_name, msg)
|
38
|
+
Kernel.require gem_name
|
39
|
+
true
|
40
|
+
rescue LoadError
|
41
|
+
log :error, msg
|
42
|
+
false
|
43
|
+
end
|
44
|
+
|
45
|
+
# Run block only if provided env var is present.
|
46
|
+
# Contains workaround for applications using Spring.
|
47
|
+
def activate(env_var)
|
48
|
+
if defined?(::Spring) && !ENV['DISABLE_SPRING']
|
49
|
+
Spring.after_fork { yield if ENV[env_var] }
|
50
|
+
elsif ENV[env_var]
|
51
|
+
yield
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
# Return absolute path to asset
|
56
|
+
def asset_path(filename)
|
57
|
+
::File.expand_path(filename, ::File.join(::File.dirname(__FILE__), "..", "assets"))
|
58
|
+
end
|
59
|
+
|
60
|
+
# Return a path to store artefact
|
61
|
+
def artefact_path(filename)
|
62
|
+
with_timestamps(
|
63
|
+
::File.join(
|
64
|
+
config.output_dir,
|
65
|
+
filename
|
66
|
+
)
|
67
|
+
)
|
68
|
+
end
|
69
|
+
|
70
|
+
private
|
71
|
+
|
72
|
+
def with_timestamps(path)
|
73
|
+
return path unless config.timestamps?
|
74
|
+
timestamps = "-#{Time.now.to_i}"
|
75
|
+
"#{path.sub(/\.\w+$/, '')}#{timestamps}#{::File.extname(path)}"
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
# TestProf configuration
|
80
|
+
class Configuration
|
81
|
+
attr_accessor :output, # IO to write output messages.
|
82
|
+
:color, # Whether to colorize output or not
|
83
|
+
:output_dir, # Directory to store artifacts
|
84
|
+
:timestamps # Whethere to use timestamped names for artifacts
|
85
|
+
|
86
|
+
def initialize
|
87
|
+
@output = $stdout
|
88
|
+
@color = true
|
89
|
+
@output_dir = "tmp"
|
90
|
+
@timestamps = false
|
91
|
+
end
|
92
|
+
|
93
|
+
def color?
|
94
|
+
color == true
|
95
|
+
end
|
96
|
+
|
97
|
+
def timestamps?
|
98
|
+
timestamps == true
|
99
|
+
end
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
require "test_prof/ruby_prof"
|
104
|
+
require "test_prof/stack_prof"
|
105
|
+
require "test_prof/event_prof"
|
106
|
+
require "test_prof/factory_doctor"
|
107
|
+
require "test_prof/factory_prof"
|
108
|
+
require "test_prof/rspec_stamp"
|
metadata
ADDED
@@ -0,0 +1,227 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: test-prof
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0.beta1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Vladimir Dementyev
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2017-07-13 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: bundler
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '1.10'
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '1.10'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: rake
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '10.0'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '10.0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: rspec
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '3.5'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '3.5'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: activerecord
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - "~>"
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '5.0'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - "~>"
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '5.0'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: factory_girl
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - "~>"
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: 4.8.0
|
76
|
+
type: :development
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - "~>"
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: 4.8.0
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: rubocop
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - "~>"
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '0.49'
|
90
|
+
type: :development
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - "~>"
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '0.49'
|
97
|
+
- !ruby/object:Gem::Dependency
|
98
|
+
name: pry-byebug
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - ">="
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: '0'
|
104
|
+
type: :development
|
105
|
+
prerelease: false
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
107
|
+
requirements:
|
108
|
+
- - ">="
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: '0'
|
111
|
+
- !ruby/object:Gem::Dependency
|
112
|
+
name: sqlite3
|
113
|
+
requirement: !ruby/object:Gem::Requirement
|
114
|
+
requirements:
|
115
|
+
- - ">="
|
116
|
+
- !ruby/object:Gem::Version
|
117
|
+
version: '0'
|
118
|
+
type: :development
|
119
|
+
prerelease: false
|
120
|
+
version_requirements: !ruby/object:Gem::Requirement
|
121
|
+
requirements:
|
122
|
+
- - ">="
|
123
|
+
- !ruby/object:Gem::Version
|
124
|
+
version: '0'
|
125
|
+
- !ruby/object:Gem::Dependency
|
126
|
+
name: sidekiq
|
127
|
+
requirement: !ruby/object:Gem::Requirement
|
128
|
+
requirements:
|
129
|
+
- - "~>"
|
130
|
+
- !ruby/object:Gem::Version
|
131
|
+
version: '4.0'
|
132
|
+
type: :development
|
133
|
+
prerelease: false
|
134
|
+
version_requirements: !ruby/object:Gem::Requirement
|
135
|
+
requirements:
|
136
|
+
- - "~>"
|
137
|
+
- !ruby/object:Gem::Version
|
138
|
+
version: '4.0'
|
139
|
+
description: "\n Ruby applications tests profiling tools.\n\n Contains tools
|
140
|
+
to anylyze factories usage, integrate with Ruby profilers,\n profile your examples
|
141
|
+
using ActiveSupport notifications (if any) and\n statically analyze your code
|
142
|
+
with custom Rubocop cops.\n "
|
143
|
+
email:
|
144
|
+
- dementiev.vm@gmail.com
|
145
|
+
executables: []
|
146
|
+
extensions: []
|
147
|
+
extra_rdoc_files: []
|
148
|
+
files:
|
149
|
+
- CHANGELOG.md
|
150
|
+
- LICENSE.txt
|
151
|
+
- README.md
|
152
|
+
- assets/flamegraph.demo.html
|
153
|
+
- assets/flamegraph.template.html
|
154
|
+
- assets/src/d3-tip.js
|
155
|
+
- assets/src/d3-tip.min.js
|
156
|
+
- assets/src/d3.flameGraph.css
|
157
|
+
- assets/src/d3.flameGraph.js
|
158
|
+
- assets/src/d3.flameGraph.min.css
|
159
|
+
- assets/src/d3.flameGraph.min.js
|
160
|
+
- assets/src/d3.v4.min.js
|
161
|
+
- guides/any_fixture.md
|
162
|
+
- guides/before_all.md
|
163
|
+
- guides/event_prof.md
|
164
|
+
- guides/factory_doctor.md
|
165
|
+
- guides/factory_prof.md
|
166
|
+
- guides/rspec_stamp.md
|
167
|
+
- guides/rubocop.md
|
168
|
+
- guides/ruby_prof.md
|
169
|
+
- guides/stack_prof.md
|
170
|
+
- lib/test-prof.rb
|
171
|
+
- lib/test_prof.rb
|
172
|
+
- lib/test_prof/any_fixture.rb
|
173
|
+
- lib/test_prof/cops/rspec/aggregate_failures.rb
|
174
|
+
- lib/test_prof/event_prof.rb
|
175
|
+
- lib/test_prof/event_prof/custom_events.rb
|
176
|
+
- lib/test_prof/event_prof/custom_events/factory_create.rb
|
177
|
+
- lib/test_prof/event_prof/custom_events/sidekiq_inline.rb
|
178
|
+
- lib/test_prof/event_prof/custom_events/sidekiq_jobs.rb
|
179
|
+
- lib/test_prof/event_prof/instrumentations/active_support.rb
|
180
|
+
- lib/test_prof/event_prof/minitest.rb
|
181
|
+
- lib/test_prof/event_prof/rspec.rb
|
182
|
+
- lib/test_prof/ext/float_duration.rb
|
183
|
+
- lib/test_prof/factory_doctor.rb
|
184
|
+
- lib/test_prof/factory_doctor/factory_girl_patch.rb
|
185
|
+
- lib/test_prof/factory_doctor/minitest.rb
|
186
|
+
- lib/test_prof/factory_doctor/rspec.rb
|
187
|
+
- lib/test_prof/factory_prof.rb
|
188
|
+
- lib/test_prof/factory_prof/factory_girl_patch.rb
|
189
|
+
- lib/test_prof/factory_prof/printers/flamegraph.rb
|
190
|
+
- lib/test_prof/factory_prof/printers/simple.rb
|
191
|
+
- lib/test_prof/logging.rb
|
192
|
+
- lib/test_prof/recipes/rspec/any_fixture.rb
|
193
|
+
- lib/test_prof/recipes/rspec/before_all.rb
|
194
|
+
- lib/test_prof/rspec_stamp.rb
|
195
|
+
- lib/test_prof/rspec_stamp/parser.rb
|
196
|
+
- lib/test_prof/rspec_stamp/rspec.rb
|
197
|
+
- lib/test_prof/rubocop.rb
|
198
|
+
- lib/test_prof/ruby_prof.rb
|
199
|
+
- lib/test_prof/ruby_prof/rspec.rb
|
200
|
+
- lib/test_prof/stack_prof.rb
|
201
|
+
- lib/test_prof/stack_prof/rspec.rb
|
202
|
+
- lib/test_prof/version.rb
|
203
|
+
homepage: http://github.com/palkan/test-prof
|
204
|
+
licenses:
|
205
|
+
- MIT
|
206
|
+
metadata: {}
|
207
|
+
post_install_message:
|
208
|
+
rdoc_options: []
|
209
|
+
require_paths:
|
210
|
+
- lib
|
211
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
212
|
+
requirements:
|
213
|
+
- - ">="
|
214
|
+
- !ruby/object:Gem::Version
|
215
|
+
version: '0'
|
216
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
217
|
+
requirements:
|
218
|
+
- - ">"
|
219
|
+
- !ruby/object:Gem::Version
|
220
|
+
version: 1.3.1
|
221
|
+
requirements: []
|
222
|
+
rubyforge_project:
|
223
|
+
rubygems_version: 2.6.11
|
224
|
+
signing_key:
|
225
|
+
specification_version: 4
|
226
|
+
summary: Ruby applications tests profiling tools
|
227
|
+
test_files: []
|