rspec-benchmark 0.2.0 → 0.3.0
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 +4 -4
- data/.travis.yml +5 -4
- data/CHANGELOG.md +7 -0
- data/Gemfile +3 -3
- data/README.md +48 -4
- data/Rakefile +1 -1
- data/lib/rspec/benchmark/comparison_matcher.rb +237 -0
- data/lib/rspec/benchmark/iteration_matcher.rb +5 -3
- data/lib/rspec/benchmark/matchers.rb +29 -2
- data/lib/rspec/benchmark/timing_matcher.rb +4 -3
- data/lib/rspec/benchmark/version.rb +1 -1
- data/spec/unit/comparison_matcher_spec.rb +183 -0
- data/spec/unit/perform_at_least_spec.rb +11 -0
- data/spec/unit/perform_under_spec.rb +8 -1
- metadata +5 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 9e2f1ed591f703a89dbf9a01070a9ba4cf893e82
|
4
|
+
data.tar.gz: f837f60f9864f23ff94e88a0d48adafff16fcd13
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 63d13b9d25a62d5ad5e3afacb0e538b0d7b5c5bdc0f35488a375401a5e6ad86cc840dddb87b711bdf7f6a303c910d6786271fbe5e56a65ee4cbaa56947c04d56
|
7
|
+
data.tar.gz: df7988107e1e39c7dbfdd2c560ddfba738d9972786671245f5273cd089c50070fabbac8cd2fa9a7f186d0990cd2f18b9a29f681224f27c7bc0ab4ee00024abb9
|
data/.travis.yml
CHANGED
@@ -6,18 +6,19 @@ script: "bundle exec rake ci"
|
|
6
6
|
rvm:
|
7
7
|
- 2.0.0
|
8
8
|
- 2.1.10
|
9
|
-
- 2.2.
|
10
|
-
- 2.3.
|
9
|
+
- 2.2.6
|
10
|
+
- 2.3.3
|
11
|
+
- 2.4.0
|
11
12
|
- ruby-head
|
12
13
|
- jruby-9000
|
13
14
|
- jruby-head
|
14
|
-
- rbx
|
15
|
+
- rbx-3
|
15
16
|
env:
|
16
17
|
global:
|
17
18
|
- JRUBY_OPTS="-Xcli.debug=true --debug"
|
18
19
|
matrix:
|
19
20
|
allow_failures:
|
20
|
-
- rvm: rbx
|
21
|
+
- rvm: rbx-3
|
21
22
|
- rvm: ruby-head
|
22
23
|
- rvm: jruby-head
|
23
24
|
fast_finish: true
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,11 @@
|
|
1
1
|
# Change log
|
2
2
|
|
3
|
+
## [v0.3.0] - 2017-02-05
|
4
|
+
|
5
|
+
### Added
|
6
|
+
* Add ComparisonMatcher with #perform_faster_than and #perform_slower_than expectations by Dmitri(@WildDima)
|
7
|
+
* Add ability to configure timing options for all Matchers such as :warmup & :time
|
8
|
+
|
3
9
|
## [v0.2.0] - 2016-11-01
|
4
10
|
|
5
11
|
### Changed
|
@@ -9,5 +15,6 @@
|
|
9
15
|
|
10
16
|
Initial release
|
11
17
|
|
18
|
+
[v0.3.0]: https://github.com/peter-murach/rspec-benchmark/compare/v0.2.0...v0.3.0
|
12
19
|
[v0.2.0]: https://github.com/peter-murach/rspec-benchmark/compare/v0.1.0...v0.2.0
|
13
20
|
[v0.1.0]: https://github.com/peter-murach/rspec-benchmark/compare/v0.1.0
|
data/Gemfile
CHANGED
data/README.md
CHANGED
@@ -2,13 +2,13 @@
|
|
2
2
|
[][gem]
|
3
3
|
[][travis]
|
4
4
|
[][codeclimate]
|
5
|
-
[][coverage]
|
6
6
|
[][inchpages]
|
7
7
|
|
8
8
|
[gem]: http://badge.fury.io/rb/rspec-benchmark
|
9
9
|
[travis]: http://travis-ci.org/piotrmurach/rspec-benchmark
|
10
10
|
[codeclimate]: https://codeclimate.com/github/piotrmurach/rspec-benchmark
|
11
|
-
[coverage]: https://coveralls.io/github/piotrmurach/rspec-benchmark
|
11
|
+
[coverage]: https://coveralls.io/github/piotrmurach/rspec-benchmark
|
12
12
|
[inchpages]: http://inch-ci.org/github/piotrmurach/rspec-benchmark
|
13
13
|
|
14
14
|
> Performance testing matchers for RSpec
|
@@ -26,6 +26,7 @@ If you are new to performance testing you may find [Caveats](#3-caveats) section
|
|
26
26
|
* [1. Usage](#1-usage)
|
27
27
|
* [1.1 Execution Time](#11-execution-time)
|
28
28
|
* [1.2 Iterations ](#12-iterations)
|
29
|
+
* [1.3 Comparison ](#13-comparison)
|
29
30
|
* [2. Filtering](#2-filtering)
|
30
31
|
* [3. Caveats](#3-caveats)
|
31
32
|
|
@@ -57,7 +58,7 @@ RSpec.configure do |config|
|
|
57
58
|
end
|
58
59
|
```
|
59
60
|
|
60
|
-
This will add the `perform_under` and `
|
61
|
+
This will add the `perform_under`, `perform_at_least`, `perform_faster_than` and `perform_slower_than` matchers to express expected performance benchmark for code executed inside the expectation.
|
61
62
|
|
62
63
|
Alternatively, you can add matchers for particular example:
|
63
64
|
|
@@ -97,6 +98,49 @@ expect { ... }.to perform_at_least(10000).ips
|
|
97
98
|
|
98
99
|
The `ips` part is optional but its usage clarifies the intent.
|
99
100
|
|
101
|
+
The performance timining of this matcher can be tweaked using the `:time` and `:warmup` parameters. These are expressed as seconds. By default `:time` is set to `0.2` and `:warmup` to `0.1` respectively. To change parameters do:
|
102
|
+
|
103
|
+
```ruby
|
104
|
+
expect { ... }.to perform_faster_than(time: 0.4, warmup: 0.2) { ... }
|
105
|
+
```
|
106
|
+
|
107
|
+
The higher values for `:time` and `:warmup` the more accurate average readings and hence more stable tests at the cost of longer test suite overall time.
|
108
|
+
|
109
|
+
### 1.3 Comparison
|
110
|
+
|
111
|
+
The `perform_faster_than` and `perform_slower_than` matchers allow you to test performance of your code compared with other. For example:
|
112
|
+
|
113
|
+
```ruby
|
114
|
+
expect { ... }.to perform_faster_than { ... }
|
115
|
+
expect { ... }.to perform_slower_than { ... }
|
116
|
+
```
|
117
|
+
|
118
|
+
And if you want to compare how much faster or slower your code is do:
|
119
|
+
|
120
|
+
```ruby
|
121
|
+
expect { ... }.to perform_faster_than { ... }.once
|
122
|
+
expect { ... }.to perform_faster_than { ... }.twice
|
123
|
+
expect { ... }.to perform_faster_than { ... }.exactly(5).times
|
124
|
+
expect { ... }.to perform_faster_than { ... }.at_least(5).times
|
125
|
+
expect { ... }.to perform_faster_than { ... }.at_most(5).times
|
126
|
+
|
127
|
+
expect { ... }.to perform_slower_than { ... }.once
|
128
|
+
expect { ... }.to perform_slower_than { ... }.twice
|
129
|
+
expect { ... }.to perform_slower_than { ... }.at_least(5).times
|
130
|
+
expect { ... }.to perform_slower_than { ... }.at_most(5).times
|
131
|
+
expect { ... }.to perform_slower_than { ... }.exactly(5).times
|
132
|
+
```
|
133
|
+
|
134
|
+
The `times` part is also optional.
|
135
|
+
|
136
|
+
The performance timining of each matcher can be tweaked using the `:time` and `:warmup` parameters. These are expressed as seconds. By default `:time` is set to `0.2` and `:warmup` to `0.1` respectively. To change parameters do:
|
137
|
+
|
138
|
+
```ruby
|
139
|
+
expect { ... }.to perform_faster_than(time: 0.4, warmup: 0.2) { ... }
|
140
|
+
```
|
141
|
+
|
142
|
+
The higher values for `:time` and `:warmup` the more accurate average readings and hence more stable tests at the cost of longer test suite overall time.
|
143
|
+
|
100
144
|
## 2 Filtering
|
101
145
|
|
102
146
|
Usually performance tests are best left for CI or occasional runs that do not affect TDD/BDD cycle. To achieve isolation you can use RSpec filters. For instance, in `spec_helper`:
|
@@ -136,4 +180,4 @@ If you have any other observations please share them!
|
|
136
180
|
|
137
181
|
## Copyright
|
138
182
|
|
139
|
-
Copyright (c) 2016 Piotr Murach. See LICENSE for further details.
|
183
|
+
Copyright (c) 2016-2017 Piotr Murach. See LICENSE for further details.
|
data/Rakefile
CHANGED
@@ -0,0 +1,237 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
module RSpec
|
4
|
+
module Benchmark
|
5
|
+
module ComparisonMatcher
|
6
|
+
# Implements the `perform_faster_than` and `perform_slower_than` matchers
|
7
|
+
#
|
8
|
+
# @api private
|
9
|
+
class Matcher
|
10
|
+
def initialize(expected, comparison_type, **options)
|
11
|
+
check_comparison(comparison_type)
|
12
|
+
@expected = expected
|
13
|
+
@comparison_type = comparison_type
|
14
|
+
@count = 1
|
15
|
+
@count_type = :at_least
|
16
|
+
time = options.fetch(:time) { 0.2 }
|
17
|
+
warmup = options.fetch(:warmup) { 0.1 }
|
18
|
+
@bench = ::Benchmark::Perf::Iteration.new(time: time, warmup: warmup)
|
19
|
+
end
|
20
|
+
|
21
|
+
# Indicates this matcher matches against a block
|
22
|
+
#
|
23
|
+
# @return [True]
|
24
|
+
#
|
25
|
+
# @api private
|
26
|
+
def supports_block_expectations?
|
27
|
+
true
|
28
|
+
end
|
29
|
+
|
30
|
+
def matcher_name
|
31
|
+
"perform_#{@comparison_type}_than"
|
32
|
+
end
|
33
|
+
|
34
|
+
# @return [Boolean]
|
35
|
+
#
|
36
|
+
# @api private
|
37
|
+
def matches?(block)
|
38
|
+
@actual = block
|
39
|
+
return false unless @actual.is_a?(Proc)
|
40
|
+
|
41
|
+
@expected_ips, @expected_stdev, = @bench.run(&@expected)
|
42
|
+
@actual_ips, @actual_stdev, = @bench.run(&@actual)
|
43
|
+
|
44
|
+
@ratio = @actual_ips / @expected_ips.to_f
|
45
|
+
|
46
|
+
case @count_type
|
47
|
+
when :at_most
|
48
|
+
at_most_comparison
|
49
|
+
when :exactly
|
50
|
+
exact_comparison
|
51
|
+
else
|
52
|
+
default_comparison
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
# Specify the minimum number of times a block
|
57
|
+
# is faster/slower than other.
|
58
|
+
# @api public
|
59
|
+
def at_least(n)
|
60
|
+
set_expected_times_count(:at_least, n)
|
61
|
+
self
|
62
|
+
end
|
63
|
+
|
64
|
+
# Specify the maximum number of times a block
|
65
|
+
# is faster/slower than another.
|
66
|
+
# @api public
|
67
|
+
def at_most(n)
|
68
|
+
set_expected_times_count(:at_most, n)
|
69
|
+
self
|
70
|
+
end
|
71
|
+
|
72
|
+
# Specify exact number of times a block
|
73
|
+
# is faster/slower than another.
|
74
|
+
# @api public
|
75
|
+
def exactly(n)
|
76
|
+
set_expected_times_count(:exactly, n)
|
77
|
+
self
|
78
|
+
end
|
79
|
+
|
80
|
+
# Specify that the code runs faster/slower exactly once.
|
81
|
+
# @api public
|
82
|
+
def once
|
83
|
+
exactly(1)
|
84
|
+
self
|
85
|
+
end
|
86
|
+
|
87
|
+
# Specify that the code runs faster/slower exactly twice.
|
88
|
+
def twice
|
89
|
+
exactly(2)
|
90
|
+
self
|
91
|
+
end
|
92
|
+
|
93
|
+
# Specify that the code runs faster/slower exactly thrice.
|
94
|
+
# @api public
|
95
|
+
def thrice
|
96
|
+
exactly(3)
|
97
|
+
self
|
98
|
+
end
|
99
|
+
|
100
|
+
# No-op, syntactic sugar.
|
101
|
+
# @api public
|
102
|
+
def times
|
103
|
+
self
|
104
|
+
end
|
105
|
+
|
106
|
+
# @api private
|
107
|
+
def failure_message
|
108
|
+
"expected given block to #{description}, but #{failure_reason}"
|
109
|
+
end
|
110
|
+
|
111
|
+
# @api private
|
112
|
+
def failure_message_when_negated
|
113
|
+
"expected given block not to #{description}, but #{failure_reason}"
|
114
|
+
end
|
115
|
+
|
116
|
+
# @api private
|
117
|
+
def description
|
118
|
+
if @count == 1
|
119
|
+
"perform #{@comparison_type} than comparison block"
|
120
|
+
else
|
121
|
+
"perform #{@comparison_type} than comparison block " \
|
122
|
+
"by #{@count_type} #{@count} times"
|
123
|
+
end
|
124
|
+
end
|
125
|
+
|
126
|
+
# @api private
|
127
|
+
def failure_reason
|
128
|
+
return "was not a block" unless @actual.is_a?(Proc)
|
129
|
+
|
130
|
+
if @ratio < 1
|
131
|
+
"performed slower by #{format('%.2f', (@ratio**-1))} times"
|
132
|
+
elsif @ratio > 1
|
133
|
+
"performed faster by #{format('%.2f', @ratio)} times"
|
134
|
+
else
|
135
|
+
"performed by the same time"
|
136
|
+
end
|
137
|
+
end
|
138
|
+
|
139
|
+
private
|
140
|
+
|
141
|
+
def convert_count(n)
|
142
|
+
case n
|
143
|
+
when Numeric then n
|
144
|
+
when :once then 1
|
145
|
+
when :twice then 2
|
146
|
+
when :thrice then 3
|
147
|
+
else
|
148
|
+
raise "The #{matcher_name} matcher is not designed to be used " \
|
149
|
+
"with #{n} count type."
|
150
|
+
end
|
151
|
+
end
|
152
|
+
|
153
|
+
def set_expected_times_count(type, n)
|
154
|
+
@count_type = type
|
155
|
+
@count = convert_count(n)
|
156
|
+
end
|
157
|
+
|
158
|
+
# @return [Boolean]
|
159
|
+
# @example
|
160
|
+
# @actual = 40
|
161
|
+
# @count = 41
|
162
|
+
# perform_faster_than { ... }.at_most(@count).times # => true
|
163
|
+
#
|
164
|
+
# @actual = 40
|
165
|
+
# @count = 41
|
166
|
+
# perform_faster_than { ... }.at_most(@count).times # => false
|
167
|
+
#
|
168
|
+
# @actual = 1/40
|
169
|
+
# @count = 41
|
170
|
+
# perform_slower_than { ... }.at_most(@count).times # => true
|
171
|
+
#
|
172
|
+
# @actual = 1/40
|
173
|
+
# @count = 41
|
174
|
+
# perform_slower_than { ... }.at_most(@count).times # => false
|
175
|
+
# @api private
|
176
|
+
def at_most_comparison
|
177
|
+
if @comparison_type == :faster
|
178
|
+
1 < @ratio && @ratio < @count
|
179
|
+
else
|
180
|
+
@count**-1 < @ratio && @ratio < 1
|
181
|
+
end
|
182
|
+
end
|
183
|
+
|
184
|
+
# Check if expected ips is faster/slower than actual ips
|
185
|
+
# exactly number of counts.
|
186
|
+
#
|
187
|
+
# @example
|
188
|
+
# @actual = 40.1
|
189
|
+
# @count = 40
|
190
|
+
# perform_faster_than { ... }.exact(@count).times # => true
|
191
|
+
#
|
192
|
+
# @actual = 40.1
|
193
|
+
# @count = 41
|
194
|
+
# perform_faster_than { ... }.exact(@count).times # => true
|
195
|
+
#
|
196
|
+
# @return [Boolean]
|
197
|
+
#
|
198
|
+
# @api private
|
199
|
+
def exact_comparison
|
200
|
+
@count == @ratio.round
|
201
|
+
end
|
202
|
+
|
203
|
+
# @return [Boolean]
|
204
|
+
# @example
|
205
|
+
# @actual = 41
|
206
|
+
# @count = 40
|
207
|
+
# perform_faster_than { ... } # => true
|
208
|
+
#
|
209
|
+
# @actual = 41
|
210
|
+
# @count = 40
|
211
|
+
# perform_faster_than { ... }.at_least(@count).times # => true
|
212
|
+
#
|
213
|
+
# @actual = 1/40
|
214
|
+
# @count = 41
|
215
|
+
# perform_slower_than { ... }.at_least(@count).times # => false
|
216
|
+
#
|
217
|
+
# @actual = 1/41
|
218
|
+
# @count = 40
|
219
|
+
# perform_slower_than { ... }.at_least(@count).times # => true
|
220
|
+
# @api private
|
221
|
+
def default_comparison
|
222
|
+
if @comparison_type == :faster
|
223
|
+
@ratio / @count > 1
|
224
|
+
else
|
225
|
+
@ratio / @count < 1 / @count.to_f
|
226
|
+
end
|
227
|
+
end
|
228
|
+
|
229
|
+
def check_comparison(type)
|
230
|
+
[:slower, :faster].include?(type) ||
|
231
|
+
(raise ArgumentError, 'comparison_type must be ' \
|
232
|
+
":faster or :slower, not `:#{type}`")
|
233
|
+
end
|
234
|
+
end # Matcher
|
235
|
+
end # ComparisonMatcher
|
236
|
+
end # Benchmark
|
237
|
+
end # RSpec
|
@@ -7,8 +7,11 @@ module RSpec
|
|
7
7
|
#
|
8
8
|
# @api private
|
9
9
|
class Matcher
|
10
|
-
def initialize(iterations, options
|
10
|
+
def initialize(iterations, **options)
|
11
11
|
@iterations = iterations
|
12
|
+
time = options.fetch(:time) { 0.2 }
|
13
|
+
warmup = options.fetch(:warmup) { 0.1 }
|
14
|
+
@bench = ::Benchmark::Perf::Iteration.new(time: time, warmup: warmup)
|
12
15
|
end
|
13
16
|
|
14
17
|
# Indicates this matcher matches against a block
|
@@ -24,8 +27,7 @@ module RSpec
|
|
24
27
|
#
|
25
28
|
# @api private
|
26
29
|
def matches?(block)
|
27
|
-
@
|
28
|
-
@average, @stddev, _ = @bench.run(&block)
|
30
|
+
@average, @stddev, = @bench.run(&block)
|
29
31
|
@iterations <= (@average + 3 * @stddev)
|
30
32
|
end
|
31
33
|
|
@@ -2,6 +2,7 @@
|
|
2
2
|
|
3
3
|
require 'rspec/benchmark/timing_matcher'
|
4
4
|
require 'rspec/benchmark/iteration_matcher'
|
5
|
+
require 'rspec/benchmark/comparison_matcher'
|
5
6
|
|
6
7
|
module RSpec
|
7
8
|
module Benchmark
|
@@ -31,7 +32,7 @@ module RSpec
|
|
31
32
|
# expect { ... }.to perform_at_least(10000).ips
|
32
33
|
#
|
33
34
|
# @api public
|
34
|
-
def perform_at_least(iterations, options
|
35
|
+
def perform_at_least(iterations, **options)
|
35
36
|
IterationMatcher::Matcher.new(iterations, options)
|
36
37
|
end
|
37
38
|
|
@@ -45,9 +46,35 @@ module RSpec
|
|
45
46
|
# expect { ... }.to peform_under(10).ms
|
46
47
|
#
|
47
48
|
# @api public
|
48
|
-
def perform_under(threshold, options
|
49
|
+
def perform_under(threshold, **options)
|
49
50
|
TimingMatcher::Matcher.new(threshold, options)
|
50
51
|
end
|
52
|
+
|
53
|
+
# Passes if code block performs faster than sample block
|
54
|
+
#
|
55
|
+
# @param [Proc] sample
|
56
|
+
#
|
57
|
+
# @example
|
58
|
+
# expect { ... }.to peform_faster_than { ... }
|
59
|
+
# expect { ... }.to peform_faster_than { ... }.at_least(5).times
|
60
|
+
#
|
61
|
+
# @api public
|
62
|
+
def perform_faster_than(**options, &sample)
|
63
|
+
ComparisonMatcher::Matcher.new(sample, :faster, options)
|
64
|
+
end
|
65
|
+
|
66
|
+
# Passes if code block performs slower than sample block
|
67
|
+
#
|
68
|
+
# @param [Proc] sample
|
69
|
+
#
|
70
|
+
# @example
|
71
|
+
# expect { ... }.to peform_slower_than { ... }
|
72
|
+
# expect { ... }.to peform_slower_than { ... }.at_most(5).times
|
73
|
+
#
|
74
|
+
# @api public
|
75
|
+
def perform_slower_than(**options, &sample)
|
76
|
+
ComparisonMatcher::Matcher.new(sample, :slower, options)
|
77
|
+
end
|
51
78
|
end # Matchers
|
52
79
|
end # Benchmark
|
53
80
|
end # RSpec
|
@@ -11,12 +11,14 @@ module RSpec
|
|
11
11
|
|
12
12
|
attr_reader :threshold
|
13
13
|
|
14
|
-
def initialize(threshold, options
|
14
|
+
def initialize(threshold, **options)
|
15
15
|
@threshold = threshold
|
16
16
|
@samples = options.fetch(:samples) { 30 }
|
17
17
|
@scale = threshold.to_s.split(/\./).last.size
|
18
18
|
@block = nil
|
19
19
|
@confidence_interval = nil
|
20
|
+
warmup = options.fetch(:warmup) { 1 }
|
21
|
+
@bench = ::Benchmark::Perf::ExecutionTime.new(warmup: warmup)
|
20
22
|
end
|
21
23
|
|
22
24
|
# Indicates this matcher matches against a block
|
@@ -34,7 +36,6 @@ module RSpec
|
|
34
36
|
def matches?(block)
|
35
37
|
@block = block
|
36
38
|
return false unless block.is_a?(Proc)
|
37
|
-
@bench = ::Benchmark::Perf::ExecutionTime.new
|
38
39
|
@average, @stddev = @bench.run(@samples, &block)
|
39
40
|
@average <= @threshold
|
40
41
|
end
|
@@ -51,7 +52,7 @@ module RSpec
|
|
51
52
|
def secs
|
52
53
|
self
|
53
54
|
end
|
54
|
-
|
55
|
+
alias sec secs
|
55
56
|
|
56
57
|
# Tell this matcher to convert threshold to ms
|
57
58
|
# @api public
|
@@ -0,0 +1,183 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
RSpec.describe RSpec::Benchmark::ComparisonMatcher::Matcher do
|
4
|
+
|
5
|
+
it "validates comparison type" do
|
6
|
+
expect {
|
7
|
+
described_class.new(-> { 1 + 2 }, :unknown)
|
8
|
+
}.to raise_error(ArgumentError, /comparison_type must be :faster or :slower, not `:unknown`/)
|
9
|
+
end
|
10
|
+
|
11
|
+
it "raises expectation error when not given a block" do
|
12
|
+
expect {
|
13
|
+
expect(1 + 1).to perform_faster_than { 'x' * 10 * 1024 }
|
14
|
+
}.to raise_error(RSpec::Expectations::ExpectationNotMetError,
|
15
|
+
"expected given block to perform faster than comparison block, but was not a block")
|
16
|
+
end
|
17
|
+
|
18
|
+
it "allows to configure matcher timings" do
|
19
|
+
bench = double(run: 100)
|
20
|
+
allow(::Benchmark::Perf::Iteration).to receive(:new).and_return(bench)
|
21
|
+
sample = -> { 'x' * 10 * 1024 }
|
22
|
+
expect { 1 << 1 }.to perform_faster_than(warmup: 0.2, time: 0.3, &sample).exactly(1).times
|
23
|
+
|
24
|
+
expect(::Benchmark::Perf::Iteration).to have_received(:new).
|
25
|
+
with(time: 0.3, warmup: 0.2)
|
26
|
+
end
|
27
|
+
|
28
|
+
describe "expect { ... }.to perform_faster_than(...)" do
|
29
|
+
it "passes if the block performs faster than sample" do
|
30
|
+
expect { 1 << 1 }.to perform_faster_than { 'x' * 10 * 1024 }
|
31
|
+
end
|
32
|
+
|
33
|
+
it "fails if the block performs slower than sample" do
|
34
|
+
expect {
|
35
|
+
expect { 'x' * 10 * 1024 }.to perform_faster_than { 1 << 1 }
|
36
|
+
}.to raise_error(/expected given block to perform faster than comparison block, but performed slower by \d+.\d+ times/)
|
37
|
+
end
|
38
|
+
|
39
|
+
context 'with exact count' do
|
40
|
+
it "passes if the block performs faster than sample" do
|
41
|
+
expect { 1 << 1 }.to perform_faster_than { 1 << 1 }.exactly(1).times
|
42
|
+
end
|
43
|
+
|
44
|
+
it "passes if the block performs specified number of times" do
|
45
|
+
expect { 1 << 1 }.to perform_faster_than { 1 << 1 }.once
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
context "with at_least count" do
|
50
|
+
it "passes if the block performs faster by count times" do
|
51
|
+
expect { 1 << 1 }.to perform_faster_than { 'x' * 10 * 1024 }.at_least(2)
|
52
|
+
end
|
53
|
+
|
54
|
+
it "fails if the block doesn't perform faster by count times" do
|
55
|
+
expect {
|
56
|
+
expect {
|
57
|
+
'x' * 10 * 1024
|
58
|
+
}.to perform_faster_than { 1 << 1 }.at_least(2).times
|
59
|
+
}.to raise_error(/expected given block to perform faster than comparison block by at_least \d+ times, but performed slower by \d+.\d+ times/)
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
context "with at_most count" do
|
64
|
+
it "passes if the block performs faster than sample" do
|
65
|
+
expect { 1 << 1 }.to perform_faster_than { 'x' * 10 * 1024 }.at_most(125)
|
66
|
+
end
|
67
|
+
|
68
|
+
it "fails if the block performs faster than sample more than in 20 times" do
|
69
|
+
expect {
|
70
|
+
expect {
|
71
|
+
1 << 1
|
72
|
+
}.to perform_faster_than { 'x' * 10 * 1024 }.at_most(2).times
|
73
|
+
}.to raise_error(/expected given block to perform faster than comparison block by at_most \d+ times, but performed faster by \d+.\d+ times/)
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
context "expect { ... }.not_to perform_faster_than(...)" do
|
79
|
+
it "passes if the block performs slower than sample" do
|
80
|
+
expect { 'x' * 10 * 1024 }.not_to perform_faster_than { 1 << 1 }
|
81
|
+
end
|
82
|
+
|
83
|
+
it "fails if the block performs faster than sample" do
|
84
|
+
expect {
|
85
|
+
expect { 1 << 1 }.not_to perform_faster_than { 'x' * 10 * 1024 }
|
86
|
+
}.to raise_error(/expected given block not to perform faster than comparison block, but performed faster by \d+.\d+ times/)
|
87
|
+
end
|
88
|
+
|
89
|
+
context 'with at_least count' do
|
90
|
+
it "passes if the block performs slower than sample" do
|
91
|
+
expect {
|
92
|
+
'x' * 10 * 1024
|
93
|
+
}.not_to perform_faster_than { 1 << 1 }.at_least(20).times
|
94
|
+
end
|
95
|
+
|
96
|
+
it "fails if the block performs faster than sample" do
|
97
|
+
expect {
|
98
|
+
expect {
|
99
|
+
1 << 1
|
100
|
+
}.not_to perform_faster_than { 'x' * 10 * 1024 }.at_least(2).times
|
101
|
+
}.to raise_error(/expected given block not to perform faster than comparison block by at_least \d+ times, but performed faster by \d+.\d+ times/)
|
102
|
+
end
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
describe "expect { ... }.not_to perform_slower_than(...)" do
|
107
|
+
it "passes if the block performs faster than sample" do
|
108
|
+
expect { 1 << 1 }.not_to perform_slower_than { 'x' * 10 * 1024 }
|
109
|
+
end
|
110
|
+
|
111
|
+
it "fails if the block performs slower than sample" do
|
112
|
+
expect {
|
113
|
+
expect { 'x' * 10 * 1024 }.not_to perform_slower_than { 1 << 1 }
|
114
|
+
}.to raise_error(/expected given block not to perform slower than comparison block, but performed slower by \d+.\d+ times/)
|
115
|
+
end
|
116
|
+
|
117
|
+
context "with at_least count" do
|
118
|
+
it "passes if the block performs faster than sample" do
|
119
|
+
expect {
|
120
|
+
1 << 1
|
121
|
+
}.not_to perform_slower_than { 'x' * 10 * 1024 }.at_least(2).times
|
122
|
+
end
|
123
|
+
|
124
|
+
it "fails if the block performs slower than sample" do
|
125
|
+
expect {
|
126
|
+
expect {
|
127
|
+
'x' * 10 * 1024
|
128
|
+
}.not_to perform_slower_than { 1 << 1 }.at_least(5).times
|
129
|
+
}.to raise_error(/expected given block not to perform slower than comparison block by at_least \d+ times, but performed slower by \d+.\d+ times/)
|
130
|
+
end
|
131
|
+
end
|
132
|
+
end
|
133
|
+
|
134
|
+
describe "expect { ... }.to perform_slower_than(...)" do
|
135
|
+
it "passes if the block performs slower than sample" do
|
136
|
+
expect { 'x' * 10 * 1024 }.to perform_slower_than { 1 << 1 }
|
137
|
+
end
|
138
|
+
|
139
|
+
it "fails if the block performs faster than sample" do
|
140
|
+
expect {
|
141
|
+
expect { 1 << 1 }.to perform_slower_than { 'x' * 10 * 1024 }
|
142
|
+
}.to raise_error(/expected given block to perform slower than comparison block, but performed faster by \d+.\d+ times/)
|
143
|
+
end
|
144
|
+
|
145
|
+
context "with at_least count" do
|
146
|
+
it "passes if the block does performs slower than sample" do
|
147
|
+
expect {
|
148
|
+
'x' * 10 * 1024
|
149
|
+
}.to perform_slower_than { 1 << 1 }.at_least(20).times
|
150
|
+
end
|
151
|
+
|
152
|
+
it "fails if the block does performs faster than sample" do
|
153
|
+
expect {
|
154
|
+
expect {
|
155
|
+
1 << 1
|
156
|
+
}.to perform_slower_than { 'x' * 10 * 1024 }.at_least(2).times
|
157
|
+
}.to raise_error(/expected given block to perform slower than comparison block by at_least \d+ times, but performed faster by \d+.\d+ times/)
|
158
|
+
end
|
159
|
+
end
|
160
|
+
|
161
|
+
context "with exact count" do
|
162
|
+
it "passes if the block performs slower than sample" do
|
163
|
+
expect { 1 << 1 }.to perform_slower_than { 1 << 1 }.exactly(1).times
|
164
|
+
end
|
165
|
+
end
|
166
|
+
|
167
|
+
context "with at_most count" do
|
168
|
+
it "passes if the block performs faster than sample" do
|
169
|
+
expect {
|
170
|
+
'x' * 10 * 1024
|
171
|
+
}.to perform_slower_than { 1 << 1 }.at_most(125).times
|
172
|
+
end
|
173
|
+
|
174
|
+
it "fails if the block performs slower than sample more than in 20 times" do
|
175
|
+
expect {
|
176
|
+
expect {
|
177
|
+
'x' * 10 * 1024
|
178
|
+
}.to perform_slower_than { 1 << 1 }.at_most(2).times
|
179
|
+
}.to raise_error(/expected given block to perform slower than comparison block by at_most \d+ times, but performed slower by \d+.\d+ times/)
|
180
|
+
end
|
181
|
+
end
|
182
|
+
end
|
183
|
+
end
|
@@ -2,6 +2,17 @@
|
|
2
2
|
|
3
3
|
RSpec.describe '#perform_at_least' do
|
4
4
|
|
5
|
+
it "allows to configure matcher timings" do
|
6
|
+
bench = double(run: [10_000, 100])
|
7
|
+
allow(::Benchmark::Perf::Iteration).to receive(:new).and_return(bench)
|
8
|
+
expect {
|
9
|
+
'x' * 1024 * 10
|
10
|
+
}.to perform_at_least(10_000, warmup: 0.2, time: 0.3)
|
11
|
+
|
12
|
+
expect(::Benchmark::Perf::Iteration).to have_received(:new).
|
13
|
+
with(time: 0.3, warmup: 0.2)
|
14
|
+
end
|
15
|
+
|
5
16
|
context "expect { ... }.to perform_at_least(...).ips" do
|
6
17
|
it "passes if the block perfoms more than 10K ips" do
|
7
18
|
expect {
|
@@ -2,11 +2,18 @@
|
|
2
2
|
|
3
3
|
RSpec.describe 'RSpec::Benchmark::TimingMatcher', '#perform_under' do
|
4
4
|
it "propagates error inside expectation" do
|
5
|
-
expect {
|
5
|
+
expect {
|
6
6
|
expect { raise 'boom' }.to perform_under(0.01).sec
|
7
7
|
}.to raise_error(StandardError, /boom/)
|
8
8
|
end
|
9
9
|
|
10
|
+
it "allows to configure warmup cycles" do
|
11
|
+
bench = double(run: [0.005, 0.00001])
|
12
|
+
allow(::Benchmark::Perf::ExecutionTime).to receive(:new).and_return(bench)
|
13
|
+
expect { 'x' * 1024 * 10 }.to perform_under(0.006, warmup: 2).sec.and_sample(2)
|
14
|
+
expect(::Benchmark::Perf::ExecutionTime).to have_received(:new).with(warmup: 2)
|
15
|
+
end
|
16
|
+
|
10
17
|
context "expect { ... }.to perfom_under(...).and_sample" do
|
11
18
|
it "passes if the block performs under threshold" do
|
12
19
|
expect {
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rspec-benchmark
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.3.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Piotr Murach
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2017-02-05 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: benchmark-perf
|
@@ -96,6 +96,7 @@ files:
|
|
96
96
|
- Rakefile
|
97
97
|
- lib/rspec-benchmark.rb
|
98
98
|
- lib/rspec/benchmark.rb
|
99
|
+
- lib/rspec/benchmark/comparison_matcher.rb
|
99
100
|
- lib/rspec/benchmark/format_time.rb
|
100
101
|
- lib/rspec/benchmark/iteration_matcher.rb
|
101
102
|
- lib/rspec/benchmark/matchers.rb
|
@@ -103,6 +104,7 @@ files:
|
|
103
104
|
- lib/rspec/benchmark/version.rb
|
104
105
|
- rspec-benchmark.gemspec
|
105
106
|
- spec/spec_helper.rb
|
107
|
+
- spec/unit/comparison_matcher_spec.rb
|
106
108
|
- spec/unit/format_time_spec.rb
|
107
109
|
- spec/unit/perform_at_least_spec.rb
|
108
110
|
- spec/unit/perform_under_spec.rb
|
@@ -134,6 +136,7 @@ specification_version: 4
|
|
134
136
|
summary: Performance testing matchers for RSpec
|
135
137
|
test_files:
|
136
138
|
- spec/spec_helper.rb
|
139
|
+
- spec/unit/comparison_matcher_spec.rb
|
137
140
|
- spec/unit/format_time_spec.rb
|
138
141
|
- spec/unit/perform_at_least_spec.rb
|
139
142
|
- spec/unit/perform_under_spec.rb
|