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 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