test-prof 0.2.2 → 0.2.4

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 5e482ddcaca18180a0606f53fd51871ba132e4a5
4
- data.tar.gz: cb321462168846d649df3237117451926a18398a
3
+ metadata.gz: 5c0da7ccf787bf83ee5ed43d069256d1183682ae
4
+ data.tar.gz: 44fd06ab01a79c6b499e4f9c36caaf56623df65c
5
5
  SHA512:
6
- metadata.gz: a0d9c32fb4241f02f5d6fa3234543fca96abffbc5f968a7e67f9e23da8f41dea1990992e82c8e54cc46feb2af2c0ceac1d1a2ef7055a6784359bef67d97c485d
7
- data.tar.gz: ad8a9004ee118da1fc8c9d2d32b290e8632ce0db0ac26803d2372fddf9efc898b28dd432f77ba89043a335724f2cddc9598742bca228486eb85e8ccea835437e
6
+ metadata.gz: 87ad75af611a473079d57cbe82d30a4c1a54eeb8d61a94190c72761c87ebad47bca6169b98f2fd84eda549c63dfce4d2dd9d11214a86a26ccebbec83895f53d4
7
+ data.tar.gz: 1cf076dc20db11b302d646ca8caf7379916b536ab24e42500cdb4378cbbc5cc74ba22411c8a15f024227023cc3bb8830c67d15e4e012ebc3099905470af17a5c
data/CHANGELOG.md CHANGED
@@ -1,6 +1,14 @@
1
1
  # Change log
2
2
 
3
- ## master
3
+ ## 0.2.4
4
+
5
+ - EventProf: Fix regression bug with examples profiling. ([@palkan][])
6
+
7
+ There was a bug when an event occurs before the example has started (e.g. in `before(:context)` hook).
8
+
9
+ ## 0.2.3
10
+
11
+ - Minor improvements. ([@palkan][])
4
12
 
5
13
  ## 0.2.2
6
14
 
data/guides/event_prof.md CHANGED
@@ -55,6 +55,8 @@ TestProf::EventProf.configure do |config|
55
55
  end
56
56
  ```
57
57
 
58
+ Or provide the `EVENT_PROF_EXAMPLES=1` env variable.
59
+
58
60
  Another useful configuration parameter – `rank_by`. It's responsible for sorting stats –
59
61
  either by the time spent in the event or by the number of occurrences:
60
62
 
data/guides/ruby_prof.md CHANGED
@@ -9,7 +9,7 @@ Install `ruby-prof` gem (>= 0.16):
9
9
  ```ruby
10
10
  # Gemfile
11
11
  group :development, :test do
12
- gem 'ruby-prof', require: false
12
+ gem 'ruby-prof', '>= 0.16.0', require: false
13
13
  end
14
14
  ```
15
15
 
data/guides/stack_prof.md CHANGED
@@ -4,12 +4,12 @@
4
4
 
5
5
  ## Instructions
6
6
 
7
- Install 'stackprof' gem (>= 0.2.7):
7
+ Install 'stackprof' gem (>= 0.2.9):
8
8
 
9
9
  ```ruby
10
10
  # Gemfile
11
11
  group :development, :test do
12
- gem 'stackprof', require: false
12
+ gem 'stackprof', '>= 0.2.9', require: false
13
13
  end
14
14
  ```
15
15
 
data/lib/test_prof.rb CHANGED
@@ -3,6 +3,7 @@
3
3
  require "fileutils"
4
4
  require "test_prof/version"
5
5
  require "test_prof/logging"
6
+ require "test_prof/utils"
6
7
 
7
8
  # Ruby applications tests profiling tools.
8
9
  #
@@ -48,7 +49,7 @@ module TestProf
48
49
  # message if it fails to load
49
50
  def require(gem_name, msg)
50
51
  Kernel.require gem_name
51
- true
52
+ block_given? ? yield : true
52
53
  rescue LoadError
53
54
  log :error, msg
54
55
  false
@@ -1,6 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require "test_prof/event_prof/instrumentations/active_support"
4
+ require "test_prof/utils/sized_ordered_set"
4
5
 
5
6
  module TestProf
6
7
  # EventProf profiles your tests and suites against custom events,
@@ -19,6 +20,8 @@ module TestProf
19
20
  # TestProf::EventProf.configure do |config|
20
21
  # config.per_example = true
21
22
  # end
23
+ #
24
+ # Or provide the EVENT_PROF_EXAMPLES=1 env variable.
22
25
  module EventProf
23
26
  # EventProf configuration
24
27
  class Configuration
@@ -34,7 +37,7 @@ module TestProf
34
37
  @event = ENV['EVENT_PROF']
35
38
  @instrumenter = :active_support
36
39
  @top_count = (ENV['EVENT_PROF_TOP'] || 5).to_i
37
- @per_example = false
40
+ @per_example = ENV['EVENT_PROF_EXAMPLES'] == '1'
38
41
  @rank_by = (ENV['EVENT_PROF_RANK'] || :time).to_sym
39
42
  end
40
43
 
@@ -82,13 +85,16 @@ module TestProf
82
85
 
83
86
  instrumenter.subscribe(event) { |time| track(time) }
84
87
 
85
- @groups = Hash.new { |h, k| h[k] = { id: k } }
86
- @examples = Hash.new { |h, k| h[k] = { id: k } }
88
+ @groups = Utils::SizedOrderedSet.new(
89
+ top_count, sort_by: rank_by
90
+ )
91
+
92
+ @examples = Utils::SizedOrderedSet.new(
93
+ top_count, sort_by: rank_by
94
+ )
87
95
 
88
96
  @total_count = 0
89
97
  @total_time = 0.0
90
-
91
- reset!
92
98
  end
93
99
 
94
100
  def track(time)
@@ -99,41 +105,47 @@ module TestProf
99
105
  @time += time
100
106
  @count += 1
101
107
 
102
- @example_time += time if config.per_example?
103
- @example_count += 1 if config.per_example?
108
+ return if @current_example.nil?
109
+
110
+ @example_time += time
111
+ @example_count += 1
104
112
  end
105
113
 
106
114
  def group_started(id)
107
- reset!
115
+ reset_group!
108
116
  @current_group = id
109
117
  end
110
118
 
111
119
  def group_finished(id)
112
- @groups[id][:time] = @time
113
- @groups[id][:count] = @count
114
- @groups[id][:examples] = @total_examples
120
+ data = { id: id, time: @time, count: @count, examples: @total_examples }
121
+
122
+ @groups << data unless data[rank_by].zero?
123
+
115
124
  @current_group = nil
116
125
  end
117
126
 
118
- def example_started(_id)
127
+ def example_started(id)
128
+ return unless config.per_example?
119
129
  reset_example!
130
+ @current_example = id
120
131
  end
121
132
 
122
133
  def example_finished(id)
123
134
  @total_examples += 1
124
135
  return unless config.per_example?
125
136
 
126
- @examples[id][:time] = @example_time
127
- @examples[id][:count] = @example_count
137
+ data = { id: id, time: @example_time, count: @example_count }
138
+ @examples << data unless data[rank_by].zero?
139
+ @current_example = nil
128
140
  end
129
141
 
130
142
  def results
131
143
  {
132
- groups: fetch_top(@groups.values)
144
+ groups: @groups.to_a
133
145
  }.tap do |data|
134
146
  next unless config.per_example?
135
147
 
136
- data[:examples] = fetch_top(@examples.values)
148
+ data[:examples] = @examples.to_a
137
149
  end
138
150
  end
139
151
 
@@ -147,21 +159,14 @@ module TestProf
147
159
 
148
160
  private
149
161
 
150
- def fetch_top(arr)
151
- arr.reject { |el| el[rank_by].zero? }
152
- .sort_by { |el| -el[rank_by] }
153
- .take(top_count)
154
- end
155
-
156
162
  def config
157
163
  EventProf.config
158
164
  end
159
165
 
160
- def reset!
166
+ def reset_group!
161
167
  @time = 0.0
162
168
  @count = 0
163
169
  @total_examples = 0
164
- reset_example!
165
170
  end
166
171
 
167
172
  def reset_example!
@@ -1,12 +1,14 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require "test_prof/ext/float_duration"
4
+ require "test_prof/ext/string_truncate"
4
5
 
5
6
  module TestProf
6
7
  module EventProf
7
8
  class RSpecListener # :nodoc:
8
9
  include Logging
9
10
  using FloatDuration
11
+ using StringTruncate
10
12
 
11
13
  NOTIFICATIONS = %i[
12
14
  example_group_started
@@ -59,7 +61,7 @@ module TestProf
59
61
 
60
62
  msgs <<
61
63
  <<~GROUP
62
- #{description} (#{location}) – #{group[:time].duration} (#{group[:count]} / #{group[:examples]})
64
+ #{description.truncate} (#{location}) – #{group[:time].duration} (#{group[:count]} / #{group[:examples]})
63
65
  GROUP
64
66
  end
65
67
 
@@ -71,7 +73,7 @@ module TestProf
71
73
  location = example[:id].metadata[:location]
72
74
  msgs <<
73
75
  <<~GROUP
74
- #{description} (#{location}) – #{example[:time].duration} (#{example[:count]})
76
+ #{description.truncate} (#{location}) – #{example[:time].duration} (#{example[:count]})
75
77
  GROUP
76
78
  end
77
79
  end
@@ -1,6 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- # Add #duration method to floats
4
3
  module TestProf
5
4
  # Extend Float with #duration method
6
5
  module FloatDuration
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: true
2
+
3
+ module TestProf
4
+ # Extend String with #truncate method
5
+ module StringTruncate
6
+ refine String do
7
+ # Truncate to the specified limit
8
+ # by replacing middle part with dots
9
+ def truncate(limit = 30)
10
+ return self unless size > limit
11
+
12
+ head = ((limit - 3) / 2)
13
+ tail = head + 3 - limit
14
+
15
+ "#{self[0..(head - 1)]}...#{self[tail..-1]}"
16
+ end
17
+ end
18
+ end
19
+ end
@@ -175,9 +175,20 @@ module TestProf
175
175
  <<~MSG
176
176
  Please, install 'ruby-prof' first:
177
177
  # Gemfile
178
- gem 'ruby-prof', require: false
178
+ gem 'ruby-prof', '>= 0.16.0', require: false
179
179
  MSG
180
- )
180
+ ) { check_ruby_prof_version }
181
+ end
182
+
183
+ def check_ruby_prof_version
184
+ if Utils.verify_gem_version('ruby-prof', at_least: '0.16.0')
185
+ true
186
+ else
187
+ log :error, <<~MGS
188
+ Please, upgrade 'ruby-prof' to version >= 0.16.0.
189
+ MGS
190
+ false
191
+ end
181
192
  end
182
193
  end
183
194
  end
@@ -114,9 +114,20 @@ module TestProf
114
114
  <<~MSG
115
115
  Please, install 'stackprof' first:
116
116
  # Gemfile
117
- gem 'stackprof', require: false
117
+ gem 'stackprof', '>= 0.2.9', require: false
118
118
  MSG
119
- )
119
+ ) { check_stack_prof_version }
120
+ end
121
+
122
+ def check_stack_prof_version
123
+ if Utils.verify_gem_version('stackprof', at_least: '0.2.9')
124
+ true
125
+ else
126
+ log :error, <<~MGS
127
+ Please, upgrade 'stackprof' to version >= 0.2.9.
128
+ MGS
129
+ false
130
+ end
120
131
  end
121
132
  end
122
133
  end
@@ -0,0 +1,18 @@
1
+ # frozen_string_literal: true
2
+
3
+ module TestProf
4
+ module Utils # :nodoc:
5
+ class << self
6
+ # Verify that loaded gem has correct version
7
+ def verify_gem_version(gem_name, at_least: nil, at_most: nil)
8
+ raise ArgumentError, "Please, provide `at_least` or `at_most` argument" if
9
+ at_least.nil? && at_most.nil?
10
+
11
+ version = Gem.loaded_specs[gem_name].version
12
+
13
+ (at_least.nil? || Gem::Version.new(at_least) <= version) &&
14
+ (at_most.nil? || Gem::Version.new(at_most) >= version)
15
+ end
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,56 @@
1
+ # frozen_string_literal: true
2
+
3
+ module TestProf
4
+ module Utils
5
+ # Ordered set with capacity
6
+ class SizedOrderedSet
7
+ include Enumerable
8
+
9
+ def initialize(max_size, sort_by: nil)
10
+ @max_size = max_size
11
+ @comparator =
12
+ if block_given?
13
+ Proc.new
14
+ elsif !sort_by.nil?
15
+ ->(x, y) { x[sort_by] >= y[sort_by] }
16
+ else
17
+ ->(x, y) { x >= y }
18
+ end
19
+ @data = []
20
+ end
21
+
22
+ def <<(item)
23
+ return if data.size == max_size &&
24
+ comparator.call(data.last, item)
25
+
26
+ # Find an index of a smaller element
27
+ index = data.bsearch_index { |x| !comparator.call(x, item) }
28
+
29
+ if index.nil?
30
+ data << item
31
+ else
32
+ data.insert(index, item)
33
+ end
34
+
35
+ data.pop if data.size > max_size
36
+ data.size
37
+ end
38
+
39
+ def each
40
+ data.each
41
+ end
42
+
43
+ def size
44
+ data.size
45
+ end
46
+
47
+ def to_a
48
+ data
49
+ end
50
+
51
+ private
52
+
53
+ attr_reader :max_size, :data, :comparator
54
+ end
55
+ end
56
+ end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module TestProf
4
- VERSION = "0.2.2"
4
+ VERSION = "0.2.4"
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: test-prof
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.2
4
+ version: 0.2.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Vladimir Dementyev
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2017-08-23 00:00:00.000000000 Z
11
+ date: 2017-08-29 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -141,6 +141,7 @@ files:
141
141
  - lib/test_prof/event_prof/minitest.rb
142
142
  - lib/test_prof/event_prof/rspec.rb
143
143
  - lib/test_prof/ext/float_duration.rb
144
+ - lib/test_prof/ext/string_truncate.rb
144
145
  - lib/test_prof/factory_default.rb
145
146
  - lib/test_prof/factory_default/factory_girl_patch.rb
146
147
  - lib/test_prof/factory_doctor.rb
@@ -167,6 +168,8 @@ files:
167
168
  - lib/test_prof/stack_prof/rspec.rb
168
169
  - lib/test_prof/tag_prof.rb
169
170
  - lib/test_prof/tag_prof/rspec.rb
171
+ - lib/test_prof/utils.rb
172
+ - lib/test_prof/utils/sized_ordered_set.rb
170
173
  - lib/test_prof/version.rb
171
174
  homepage: http://github.com/palkan/test-prof
172
175
  licenses: