rspec-benchmark 0.2.0 → 0.3.0

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: 6e97c37d92aad25cc4818e165c58fce09b261bd2
4
- data.tar.gz: 9ca0eb8504cb3ee565f2c0708c1e5595e6563de7
3
+ metadata.gz: 9e2f1ed591f703a89dbf9a01070a9ba4cf893e82
4
+ data.tar.gz: f837f60f9864f23ff94e88a0d48adafff16fcd13
5
5
  SHA512:
6
- metadata.gz: e3f034d4c0b725f1e94ead47cb8ca826757f7dad1c3e948a92b60fbfa2434935ed91a5bec606a7c411c2ecca498464499393909eb089a305793218eec2b38612
7
- data.tar.gz: 87079a2e2953c7e90bc05623928a858a06514f5f7860dc45db9eaa2b7682bb345ecff4eb592a44fb506ec54dbcd4d395988bca6b0d773319920b8a278bda2ce1
6
+ metadata.gz: 63d13b9d25a62d5ad5e3afacb0e538b0d7b5c5bdc0f35488a375401a5e6ad86cc840dddb87b711bdf7f6a303c910d6786271fbe5e56a65ee4cbaa56947c04d56
7
+ data.tar.gz: df7988107e1e39c7dbfdd2c560ddfba738d9972786671245f5273cd089c50070fabbac8cd2fa9a7f186d0990cd2f18b9a29f681224f27c7bc0ab4ee00024abb9
@@ -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.5
10
- - 2.3.1
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
@@ -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
@@ -2,8 +2,8 @@ source 'https://rubygems.org'
2
2
 
3
3
  gemspec
4
4
 
5
- group :metrics do
6
- gem 'coveralls', '~> 0.8.9'
7
- gem 'simplecov', '~> 0.10.0'
5
+ group :test do
6
+ gem 'coveralls', '~> 0.8.15'
7
+ gem 'simplecov', '~> 0.12.0'
8
8
  gem 'yardstick', '~> 0.9.9'
9
9
  end
data/README.md CHANGED
@@ -2,13 +2,13 @@
2
2
  [![Gem Version](https://badge.fury.io/rb/rspec-benchmark.svg)][gem]
3
3
  [![Build Status](https://secure.travis-ci.org/piotrmurach/rspec-benchmark.svg?branch=master)][travis]
4
4
  [![Code Climate](https://codeclimate.com/github/piotrmurach/rspec-benchmark/badges/gpa.svg)][codeclimate]
5
- [![Coverage Status](https://coveralls.io/repos/github/piotrmurach/rspec-benchmark/badge.svg?branch=master)][coverage]
5
+ [![Coverage Status](https://coveralls.io/repos/github/piotrmurach/rspec-benchmark/badge.svg)][coverage]
6
6
  [![Inline docs](http://inch-ci.org/github/piotrmurach/rspec-benchmark.svg?branch=master)][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?branch=master
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 `perform_at_least` matchers to express expected performance benchmark from code executed inside the expectation.
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
@@ -5,6 +5,6 @@ require "bundler/gem_tasks"
5
5
  FileList['tasks/**/*.rake'].each(&method(:import))
6
6
 
7
7
  desc 'Run all specs'
8
- task ci: %w[ spec ]
8
+ task ci: %w[ coverage ]
9
9
 
10
10
  task default: :spec
@@ -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
- @bench = ::Benchmark::Perf::Iteration.new
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
- alias_method :sec, :secs
55
+ alias sec secs
55
56
 
56
57
  # Tell this matcher to convert threshold to ms
57
58
  # @api public
@@ -2,6 +2,6 @@
2
2
 
3
3
  module RSpec
4
4
  module Benchmark
5
- VERSION = "0.2.0"
5
+ VERSION = "0.3.0"
6
6
  end # Benchmark
7
7
  end # RSpec
@@ -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.2.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: 2016-11-01 00:00:00.000000000 Z
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