test-prof 0.1.0.beta1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (56) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG.md +7 -0
  3. data/LICENSE.txt +21 -0
  4. data/README.md +103 -0
  5. data/assets/flamegraph.demo.html +173 -0
  6. data/assets/flamegraph.template.html +196 -0
  7. data/assets/src/d3-tip.js +352 -0
  8. data/assets/src/d3-tip.min.js +1 -0
  9. data/assets/src/d3.flameGraph.css +92 -0
  10. data/assets/src/d3.flameGraph.js +459 -0
  11. data/assets/src/d3.flameGraph.min.css +1 -0
  12. data/assets/src/d3.flameGraph.min.js +1 -0
  13. data/assets/src/d3.v4.min.js +8 -0
  14. data/guides/any_fixture.md +60 -0
  15. data/guides/before_all.md +98 -0
  16. data/guides/event_prof.md +97 -0
  17. data/guides/factory_doctor.md +64 -0
  18. data/guides/factory_prof.md +85 -0
  19. data/guides/rspec_stamp.md +53 -0
  20. data/guides/rubocop.md +48 -0
  21. data/guides/ruby_prof.md +61 -0
  22. data/guides/stack_prof.md +43 -0
  23. data/lib/test-prof.rb +3 -0
  24. data/lib/test_prof/any_fixture.rb +67 -0
  25. data/lib/test_prof/cops/rspec/aggregate_failures.rb +140 -0
  26. data/lib/test_prof/event_prof/custom_events/factory_create.rb +51 -0
  27. data/lib/test_prof/event_prof/custom_events/sidekiq_inline.rb +48 -0
  28. data/lib/test_prof/event_prof/custom_events/sidekiq_jobs.rb +38 -0
  29. data/lib/test_prof/event_prof/custom_events.rb +5 -0
  30. data/lib/test_prof/event_prof/instrumentations/active_support.rb +16 -0
  31. data/lib/test_prof/event_prof/minitest.rb +3 -0
  32. data/lib/test_prof/event_prof/rspec.rb +94 -0
  33. data/lib/test_prof/event_prof.rb +177 -0
  34. data/lib/test_prof/ext/float_duration.rb +14 -0
  35. data/lib/test_prof/factory_doctor/factory_girl_patch.rb +12 -0
  36. data/lib/test_prof/factory_doctor/minitest.rb +3 -0
  37. data/lib/test_prof/factory_doctor/rspec.rb +96 -0
  38. data/lib/test_prof/factory_doctor.rb +133 -0
  39. data/lib/test_prof/factory_prof/factory_girl_patch.rb +12 -0
  40. data/lib/test_prof/factory_prof/printers/flamegraph.rb +71 -0
  41. data/lib/test_prof/factory_prof/printers/simple.rb +28 -0
  42. data/lib/test_prof/factory_prof.rb +140 -0
  43. data/lib/test_prof/logging.rb +25 -0
  44. data/lib/test_prof/recipes/rspec/any_fixture.rb +21 -0
  45. data/lib/test_prof/recipes/rspec/before_all.rb +23 -0
  46. data/lib/test_prof/rspec_stamp/parser.rb +103 -0
  47. data/lib/test_prof/rspec_stamp/rspec.rb +91 -0
  48. data/lib/test_prof/rspec_stamp.rb +135 -0
  49. data/lib/test_prof/rubocop.rb +3 -0
  50. data/lib/test_prof/ruby_prof/rspec.rb +13 -0
  51. data/lib/test_prof/ruby_prof.rb +194 -0
  52. data/lib/test_prof/stack_prof/rspec.rb +13 -0
  53. data/lib/test_prof/stack_prof.rb +120 -0
  54. data/lib/test_prof/version.rb +5 -0
  55. data/lib/test_prof.rb +108 -0
  56. 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
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ module TestProf
4
+ VERSION = "0.1.0.beta1"
5
+ 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: []