test-prof 0.1.0.beta4 → 0.1.0.pre2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +10 -0
- data/.rspec +2 -0
- data/.rubocop.yml +69 -0
- data/.travis.yml +5 -0
- data/Gemfile +4 -0
- data/README.md +2 -16
- data/Rakefile +8 -0
- data/bin/setup +8 -0
- data/circle.yml +11 -0
- data/guides/any_fixture.md +1 -1
- data/guides/ruby_prof.md +0 -2
- data/guides/stack_prof.md +1 -5
- data/lib/test_prof.rb +6 -31
- data/lib/test_prof/event_prof.rb +4 -2
- data/lib/test_prof/event_prof/custom_events.rb +3 -3
- data/lib/test_prof/event_prof/custom_events/factory_create.rb +9 -11
- data/lib/test_prof/event_prof/custom_events/sidekiq_inline.rb +9 -11
- data/lib/test_prof/event_prof/custom_events/sidekiq_jobs.rb +11 -13
- data/lib/test_prof/event_prof/rspec.rb +1 -5
- data/lib/test_prof/factory_doctor.rb +9 -11
- data/lib/test_prof/factory_doctor/rspec.rb +3 -5
- data/lib/test_prof/ruby_prof.rb +12 -6
- data/lib/test_prof/stack_prof.rb +7 -14
- data/lib/test_prof/version.rb +1 -1
- data/spec/integrations/any_fixture_spec.rb +11 -0
- data/spec/integrations/before_all_spec.rb +11 -0
- data/spec/integrations/event_prof_spec.rb +100 -0
- data/spec/integrations/factory_doctor_spec.rb +20 -0
- data/spec/integrations/fixtures/rspec/any_fixture_fixture.rb +37 -0
- data/spec/integrations/fixtures/rspec/before_all_fixture.rb +32 -0
- data/spec/integrations/fixtures/rspec/event_prof_factory_create_fixture.rb +23 -0
- data/spec/integrations/fixtures/rspec/event_prof_fixture.rb +51 -0
- data/spec/integrations/fixtures/rspec/event_prof_sidekiq_fixture.rb +54 -0
- data/spec/integrations/fixtures/rspec/factory_doctor_fixture.rb +33 -0
- data/spec/spec_helper.rb +38 -0
- data/spec/support/ar_models.rb +43 -0
- data/spec/support/instrumenter_stub.rb +19 -0
- data/spec/support/integration_helpers.rb +13 -0
- data/spec/support/transactional_context.rb +11 -0
- data/spec/test_prof/any_fixture_spec.rb +66 -0
- data/spec/test_prof/event_prof_spec.rb +138 -0
- data/spec/test_prof/ext/float_duration_spec.rb +12 -0
- data/spec/test_prof/factory_doctor_spec.rb +84 -0
- data/spec/test_prof/ruby_prof_spec.rb +109 -0
- data/spec/test_prof/stack_prof_spec.rb +73 -0
- data/spec/test_prof_spec.rb +23 -0
- data/test-prof.gemspec +35 -0
- metadata +34 -49
- data/CHANGELOG.md +0 -7
- data/assets/flamegraph.demo.html +0 -173
- data/assets/flamegraph.template.html +0 -196
- data/assets/src/d3-tip.js +0 -352
- data/assets/src/d3-tip.min.js +0 -1
- data/assets/src/d3.flameGraph.css +0 -92
- data/assets/src/d3.flameGraph.js +0 -459
- data/assets/src/d3.flameGraph.min.css +0 -1
- data/assets/src/d3.flameGraph.min.js +0 -1
- data/assets/src/d3.v4.min.js +0 -8
- data/guides/factory_default.md +0 -109
- data/guides/factory_prof.md +0 -85
- data/guides/rspec_stamp.md +0 -53
- data/guides/rubocop.md +0 -48
- data/guides/tag_prof.md +0 -52
- data/guides/tests_sampling.md +0 -24
- data/lib/test_prof/cops/rspec/aggregate_failures.rb +0 -140
- data/lib/test_prof/factory_default.rb +0 -58
- data/lib/test_prof/factory_default/factory_girl_patch.rb +0 -22
- data/lib/test_prof/factory_prof.rb +0 -140
- data/lib/test_prof/factory_prof/factory_girl_patch.rb +0 -12
- data/lib/test_prof/factory_prof/printers/flamegraph.rb +0 -71
- data/lib/test_prof/factory_prof/printers/simple.rb +0 -28
- data/lib/test_prof/recipes/minitest/sample.rb +0 -29
- data/lib/test_prof/recipes/rspec/factory_default.rb +0 -9
- data/lib/test_prof/recipes/rspec/sample.rb +0 -13
- data/lib/test_prof/rspec_stamp.rb +0 -135
- data/lib/test_prof/rspec_stamp/parser.rb +0 -103
- data/lib/test_prof/rspec_stamp/rspec.rb +0 -95
- data/lib/test_prof/rubocop.rb +0 -3
- data/lib/test_prof/tag_prof.rb +0 -8
- data/lib/test_prof/tag_prof/rspec.rb +0 -84
@@ -1,103 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require "ripper"
|
4
|
-
|
5
|
-
# rubocop: disable Metrics/CyclomaticComplexity
|
6
|
-
|
7
|
-
module TestProf
|
8
|
-
module RSpecStamp
|
9
|
-
# Parse examples headers
|
10
|
-
module Parser
|
11
|
-
# Contains the result of parsing
|
12
|
-
class Result
|
13
|
-
attr_accessor :fname, :desc
|
14
|
-
attr_reader :tags, :htags
|
15
|
-
|
16
|
-
def add_tag(v)
|
17
|
-
@tags ||= []
|
18
|
-
@tags << v
|
19
|
-
end
|
20
|
-
|
21
|
-
def add_htag(k, v)
|
22
|
-
@htags ||= []
|
23
|
-
@htags << [k, v]
|
24
|
-
end
|
25
|
-
end
|
26
|
-
|
27
|
-
class << self
|
28
|
-
def parse(code)
|
29
|
-
sexp = Ripper.sexp(code)
|
30
|
-
return unless sexp
|
31
|
-
|
32
|
-
# sexp has the following format:
|
33
|
-
# [:program,
|
34
|
-
# [
|
35
|
-
# [
|
36
|
-
# :command,
|
37
|
-
# [:@ident, "it", [1, 0]],
|
38
|
-
# [:args_add_block, [ ... ]]
|
39
|
-
# ]
|
40
|
-
# ]
|
41
|
-
# ]
|
42
|
-
#
|
43
|
-
# or
|
44
|
-
#
|
45
|
-
# [:program,
|
46
|
-
# [
|
47
|
-
# [
|
48
|
-
# :vcall,
|
49
|
-
# [:@ident, "it", [1, 0]]
|
50
|
-
# ]
|
51
|
-
# ]
|
52
|
-
# ]
|
53
|
-
res = Result.new
|
54
|
-
|
55
|
-
fcall = sexp[1][0][1]
|
56
|
-
fcall = fcall[1] if fcall.first == :fcall
|
57
|
-
res.fname = fcall[1]
|
58
|
-
|
59
|
-
args_block = sexp[1][0][2]
|
60
|
-
|
61
|
-
return res if args_block.nil?
|
62
|
-
|
63
|
-
args_block = args_block[1] if args_block.first == :arg_paren
|
64
|
-
|
65
|
-
args = args_block[1]
|
66
|
-
|
67
|
-
if args.first.first == :string_literal
|
68
|
-
res.desc = parse_literal(args.shift)
|
69
|
-
end
|
70
|
-
|
71
|
-
parse_arg(res, args.shift) until args.empty?
|
72
|
-
|
73
|
-
res
|
74
|
-
end
|
75
|
-
|
76
|
-
private
|
77
|
-
|
78
|
-
def parse_arg(res, arg)
|
79
|
-
if arg.first == :symbol_literal
|
80
|
-
res.add_tag parse_literal(arg)
|
81
|
-
elsif arg.first == :bare_assoc_hash
|
82
|
-
parse_hash(res, arg[1])
|
83
|
-
end
|
84
|
-
end
|
85
|
-
|
86
|
-
def parse_hash(res, hash_arg)
|
87
|
-
hash_arg.each do |(_, label, val)|
|
88
|
-
res.add_htag label[1][0..-2].to_sym, parse_literal(val)
|
89
|
-
end
|
90
|
-
end
|
91
|
-
|
92
|
-
# Expr of the form:
|
93
|
-
# [:string_literal, [:string_content, [:@tstring_content, "is", [1, 4]]]]
|
94
|
-
def parse_literal(expr)
|
95
|
-
val = expr[1][1][1]
|
96
|
-
val = val.to_sym if expr[0] == :symbol_literal ||
|
97
|
-
expr[0] == :assoc_new
|
98
|
-
val
|
99
|
-
end
|
100
|
-
end
|
101
|
-
end
|
102
|
-
end
|
103
|
-
end
|
@@ -1,95 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module TestProf
|
4
|
-
module RSpecStamp
|
5
|
-
class RSpecListener # :nodoc:
|
6
|
-
include Logging
|
7
|
-
|
8
|
-
NOTIFICATIONS = %i[
|
9
|
-
example_failed
|
10
|
-
].freeze
|
11
|
-
|
12
|
-
def initialize
|
13
|
-
@failed = 0
|
14
|
-
@ignored = 0
|
15
|
-
@total = 0
|
16
|
-
@examples = Hash.new { |h, k| h[k] = [] }
|
17
|
-
end
|
18
|
-
|
19
|
-
def example_failed(notification)
|
20
|
-
return if notification.example.pending?
|
21
|
-
|
22
|
-
location = notification.example.metadata[:location]
|
23
|
-
|
24
|
-
file, line = location.split(":")
|
25
|
-
|
26
|
-
@examples[file] << line.to_i
|
27
|
-
end
|
28
|
-
|
29
|
-
def stamp!
|
30
|
-
@examples.each do |file, lines|
|
31
|
-
stamp_file(file, lines.uniq)
|
32
|
-
end
|
33
|
-
|
34
|
-
msgs = []
|
35
|
-
|
36
|
-
msgs <<
|
37
|
-
<<~MSG
|
38
|
-
RSpec Stamp results
|
39
|
-
|
40
|
-
Total patches: #{@total}
|
41
|
-
Total files: #{@examples.keys.size}
|
42
|
-
|
43
|
-
Failed patches: #{@failed}
|
44
|
-
Ignored files: #{@ignored}
|
45
|
-
MSG
|
46
|
-
|
47
|
-
log :info, msgs.join
|
48
|
-
end
|
49
|
-
|
50
|
-
private
|
51
|
-
|
52
|
-
def stamp_file(file, lines)
|
53
|
-
@total += lines.size
|
54
|
-
return if ignored?(file)
|
55
|
-
|
56
|
-
log :info, "(dry-run) Patching #{file}" if dry_run?
|
57
|
-
|
58
|
-
code = File.readlines(file)
|
59
|
-
|
60
|
-
@failed += RSpecStamp.apply_tags(code, lines, RSpecStamp.config.tags)
|
61
|
-
|
62
|
-
File.write(file, code.join) unless dry_run?
|
63
|
-
end
|
64
|
-
|
65
|
-
def ignored?(file)
|
66
|
-
ignored = RSpecStamp.config.ignore_files.find do |pattern|
|
67
|
-
file =~ pattern
|
68
|
-
end
|
69
|
-
|
70
|
-
return unless ignored
|
71
|
-
log :warn, "Ignore stamping file: #{file}"
|
72
|
-
@ignored += 1
|
73
|
-
end
|
74
|
-
|
75
|
-
def dry_run?
|
76
|
-
RSpecStamp.config.dry_run?
|
77
|
-
end
|
78
|
-
end
|
79
|
-
end
|
80
|
-
end
|
81
|
-
|
82
|
-
# Register EventProf listener
|
83
|
-
TestProf.activate('RSTAMP') do
|
84
|
-
RSpec.configure do |config|
|
85
|
-
listener = TestProf::RSpecStamp::RSpecListener.new
|
86
|
-
|
87
|
-
config.before(:suite) do
|
88
|
-
config.reporter.register_listener(
|
89
|
-
listener, *TestProf::RSpecStamp::RSpecListener::NOTIFICATIONS
|
90
|
-
)
|
91
|
-
end
|
92
|
-
|
93
|
-
config.after(:suite) { listener.stamp! }
|
94
|
-
end
|
95
|
-
end
|
data/lib/test_prof/rubocop.rb
DELETED
data/lib/test_prof/tag_prof.rb
DELETED
@@ -1,84 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require "test_prof/ext/float_duration"
|
4
|
-
|
5
|
-
module TestProf
|
6
|
-
module TagProf
|
7
|
-
class RSpecListener # :nodoc:
|
8
|
-
include Logging
|
9
|
-
using FloatDuration
|
10
|
-
|
11
|
-
NOTIFICATIONS = %i[
|
12
|
-
example_started
|
13
|
-
example_finished
|
14
|
-
].freeze
|
15
|
-
|
16
|
-
def initialize
|
17
|
-
@tag = ENV['TAG_PROF'].to_sym
|
18
|
-
@tags = Hash.new { |h, k| h[k] = { val: k, count: 0, time: 0.0 } }
|
19
|
-
|
20
|
-
log :info, "TagProf enabled (#{@tag})"
|
21
|
-
end
|
22
|
-
|
23
|
-
def example_started(_notification)
|
24
|
-
@ts = Time.now
|
25
|
-
end
|
26
|
-
|
27
|
-
def example_finished(notification)
|
28
|
-
return if notification.example.pending?
|
29
|
-
|
30
|
-
tag = notification.example.metadata.fetch(@tag, :__unknown__)
|
31
|
-
|
32
|
-
@tags[tag][:count] += 1
|
33
|
-
@tags[tag][:time] += (Time.now - @ts)
|
34
|
-
end
|
35
|
-
|
36
|
-
def print
|
37
|
-
msgs = []
|
38
|
-
|
39
|
-
msgs <<
|
40
|
-
<<~MSG
|
41
|
-
TagProf report for #{@tag}
|
42
|
-
MSG
|
43
|
-
|
44
|
-
msgs << format(
|
45
|
-
"%15s %12s %6s %6s %6s %12s",
|
46
|
-
@tag,
|
47
|
-
'time', 'total', '%total', '%time', 'avg'
|
48
|
-
)
|
49
|
-
|
50
|
-
msgs << ""
|
51
|
-
|
52
|
-
total = @tags.values.sum { |v| v[:count] }
|
53
|
-
total_time = @tags.values.sum { |v| v[:time] }
|
54
|
-
|
55
|
-
@tags.values.sort_by { |v| -v[:time] }.each do |tag|
|
56
|
-
msgs << format(
|
57
|
-
"%15s %12s %6d %6.2f %6.2f %12s",
|
58
|
-
tag[:val], tag[:time].duration, tag[:count],
|
59
|
-
100 * tag[:count].to_f / total,
|
60
|
-
100 * tag[:time] / total_time,
|
61
|
-
(tag[:time] / tag[:count]).duration
|
62
|
-
)
|
63
|
-
end
|
64
|
-
|
65
|
-
log :info, msgs.join("\n")
|
66
|
-
end
|
67
|
-
end
|
68
|
-
end
|
69
|
-
end
|
70
|
-
|
71
|
-
# Register TagProf listener
|
72
|
-
TestProf.activate('TAG_PROF') do
|
73
|
-
RSpec.configure do |config|
|
74
|
-
listener = TestProf::TagProf::RSpecListener.new
|
75
|
-
|
76
|
-
config.before(:suite) do
|
77
|
-
config.reporter.register_listener(
|
78
|
-
listener, *TestProf::TagProf::RSpecListener::NOTIFICATIONS
|
79
|
-
)
|
80
|
-
end
|
81
|
-
|
82
|
-
config.after(:suite) { listener.print }
|
83
|
-
end
|
84
|
-
end
|