rspec-benchmark 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 7284782b6fbaacc643bbe29f58c30aa05985b9c7
4
+ data.tar.gz: 8e5fd4afde4a6cba55e537d8399652a286675021
5
+ SHA512:
6
+ metadata.gz: 72f9771b9edea737412eb8e241d70f4dd56866632c267ce72b71719567cd0b19d7769b4425067050d90ae84bd049a0cc6f75e17f2da97f1fdcc92747b2bea06f
7
+ data.tar.gz: 951f9b31da5bea5c0df8db36fc2a2a2befeef46d92e061f5dcc8e08f6c08489f36035f40e3321199439f961ec27eeb5f28fbe48daed4da87bf612c5e85f63023
@@ -0,0 +1,14 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /Gemfile.lock
4
+ /_yardoc/
5
+ /coverage/
6
+ /doc/
7
+ /pkg/
8
+ /spec/reports/
9
+ /tmp/
10
+ *.bundle
11
+ *.so
12
+ *.o
13
+ *.a
14
+ mkmf.log
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --color
2
+ --require spec_helper
@@ -0,0 +1,28 @@
1
+ ---
2
+ language: ruby
3
+ sudo: false
4
+ cache: bundler
5
+ bundler_args: --without yard benchmarks
6
+ script: "bundle exec rake ci"
7
+ rvm:
8
+ - 1.9.3
9
+ - 2.0
10
+ - 2.1
11
+ - 2.2
12
+ - ruby-head
13
+ - jruby-19mode
14
+ - jruby
15
+ - jruby-head
16
+ - rbx-2
17
+ env:
18
+ global:
19
+ - JRUBY_OPTS="-Xcli.debug=true --debug"
20
+ matrix:
21
+ allow_failures:
22
+ - rvm: ruby-head
23
+ - rvm: jruby-head
24
+ fast_finish: true
25
+ branches:
26
+ only: master
27
+ notifications:
28
+ email: false
@@ -0,0 +1,7 @@
1
+ # Change log
2
+
3
+ ## [v0.1.0] - 2016-01-25
4
+
5
+ Initial release
6
+
7
+ [v0.1.0]: https://github.com/peter-murach/rspec-benchmark/compare/v0.1.0
data/Gemfile ADDED
@@ -0,0 +1,9 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gemspec
4
+
5
+ group :metrics do
6
+ gem 'coveralls', '~> 0.8.9'
7
+ gem 'simplecov', '~> 0.10.0'
8
+ gem 'yardstick', '~> 0.9.9'
9
+ end
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2016 Piotr Murach
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,137 @@
1
+ # RSpec::Benchmark
2
+ [![Gem Version](https://badge.fury.io/rb/rspec-benchmark.svg)][gem]
3
+ [![Build Status](https://secure.travis-ci.org/peter-murach/rspec-benchmark.svg?branch=master)][travis]
4
+ [![Code Climate](https://codeclimate.com/github/peter-murach/rspec-benchmark/badges/gpa.svg)][codeclimate]
5
+ [![Coverage Status](https://coveralls.io/repos/github/peter-murach/rspec-benchmark/badge.svg?branch=master)][coverage]
6
+ [![Inline docs](http://inch-ci.org/github/peter-murach/rspec-benchmark.svg?branch=master)][inchpages]
7
+
8
+ [gem]: http://badge.fury.io/rb/rspec-benchmark
9
+ [travis]: http://travis-ci.org/peter-murach/rspec-benchmark
10
+ [codeclimate]: https://codeclimate.com/github/peter-murach/rspec-benchmark
11
+ [coverage]: https://coveralls.io/github/peter-murach/rspec-benchmark?branch=master
12
+ [inchpages]: http://inch-ci.org/github/peter-murach/rspec-benchmark
13
+
14
+ > Performance testing matchers for RSpec
15
+
16
+ **RSpec::Benchmark** uses [benchmark-perf](https://github.com/peter-murach/benchmark-perf) for measurements.
17
+
18
+ ## Why?
19
+
20
+ Integration and unit tests ensure that changing code maintains expected functionality. What is not guaranteed is the code changes impact on library performance. It is easy to refactor your way out of fast to slow code.
21
+
22
+ If you are new to performance testing you may find [Caveats](#3-caveats) section helpful.
23
+
24
+ ## Contents
25
+
26
+ * [1. Usage](#1-usage)
27
+ * [2. Filtering](#2-filtering)
28
+ * [3. Caveats](#3-caveats)
29
+
30
+ ## Installation
31
+
32
+ Add this line to your application's Gemfile:
33
+
34
+ ```ruby
35
+ gem 'rspec-benchmark'
36
+ ```
37
+
38
+ And then execute:
39
+
40
+ $ bundle
41
+
42
+ Or install it yourself as:
43
+
44
+ $ gem install rspec-benchmark
45
+
46
+ ## 1. Usage
47
+
48
+ For matchers to be available globally, in `spec_helper.rb` do:
49
+
50
+ ```ruby
51
+ require 'rspec-benchmark'
52
+
53
+ RSpec.configure do |config|
54
+ config.include RSpec::Benchmark::Matchers
55
+ end
56
+ ```
57
+
58
+ This will add the `perform_under` and `perform_at_least` matchers to express expected performance benchmark from code executed inside the expectation.
59
+
60
+ Alternatively, you can add matchers for particular example:
61
+
62
+ ```ruby
63
+ RSpec.describe "Performance testing" do
64
+ include RSpec::Benchmark::Matchers
65
+ end
66
+ ```
67
+
68
+ ### 1.1 Execution time
69
+
70
+ The `perform_under` matcher answers the question of how long does it take to perform a given block of code on average. The measurements are taken executing the block of code in a child process for accurent cpu times.
71
+
72
+ ```ruby
73
+ expect { ... }.to perform_under(0.01).sec
74
+ ```
75
+
76
+ All measurements are assumed to be expressed as seconds. However, you can also provide time in `ms`, `us` and `ns`. The equivalent example in `ms` would be:
77
+
78
+ ```ruby
79
+ expect { ... }.to perform_under(10).ms
80
+ ```
81
+
82
+ by default the above code will be sampled `30` times but you can change this by using `and_sample` like so:
83
+
84
+ ```ruby
85
+ expect { ... }.to perform_under(0.01).and_sample(10)
86
+ ```
87
+
88
+ ### 1.2 Iterations
89
+
90
+ The `perform_at_least` matcher allows you to establish performance benchmark of how many iterations per second a given block of code should perform. For example, to expect a given code to perform at least 10K iterations per second do:
91
+
92
+ ```ruby
93
+ expect { ... }.to perform_at_least(10000).ips
94
+ ```
95
+
96
+ The `ips` part is optional but its usage clarifies the intent.
97
+
98
+ ## 2 Filtering
99
+
100
+ 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`:
101
+
102
+ ```
103
+ config.filter_run_excluding performance: true
104
+ ```
105
+
106
+ and then in your example group do:
107
+
108
+ ```ruby
109
+ RSpec.describe ..., performance: true do
110
+ ...
111
+ end
112
+ ```
113
+
114
+ Another option is to simply isolate the performance specs in separate directory suc as `spec/performance/...` and add custom rake task.
115
+
116
+ ## 3 Caveats
117
+
118
+ When writing performance tests things to be mindful are:
119
+
120
+ + The tests may **potentially be flaky** thus its best to use sensible boundaries:
121
+ - **too strict** boundaries may cause false positives, making tests fail
122
+ - **too relaxed** boundaries may also lead to false positives missing actual performance regressions
123
+ + Generally performance tests will be **slow**, but you may try to avoid _unnecessarily_ slow tests by choosing smaller maximum value for sampling
124
+
125
+ If you have any other observations please share them!
126
+
127
+ ## Contributing
128
+
129
+ 1. Fork it ( https://github.com/peter-murach/rspec-benchmark/fork )
130
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
131
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
132
+ 4. Push to the branch (`git push origin my-new-feature`)
133
+ 5. Create a new Pull Request
134
+
135
+ ## Copyright
136
+
137
+ Copyright (c) 2016 Piotr Murach. See LICENSE for further details.
@@ -0,0 +1,10 @@
1
+ # encoding: utf-8
2
+
3
+ require "bundler/gem_tasks"
4
+
5
+ FileList['tasks/**/*.rake'].each(&method(:import))
6
+
7
+ desc 'Run all specs'
8
+ task ci: %w[ spec ]
9
+
10
+ task default: :spec
@@ -0,0 +1,3 @@
1
+ # encoding: utf-8
2
+
3
+ require 'rspec/benchmark'
@@ -0,0 +1,7 @@
1
+ # encoding: utf-8
2
+
3
+ require 'benchmark-perf'
4
+
5
+ require 'rspec/benchmark/format_time'
6
+ require 'rspec/benchmark/matchers'
7
+ require 'rspec/benchmark/version'
@@ -0,0 +1,29 @@
1
+ # encoding: utf-8
2
+
3
+ module RSpec
4
+ module Benchmark
5
+ # Format time for easy matcher reporting
6
+ #
7
+ # @param [Float] time
8
+ # the time to format
9
+ #
10
+ # @return [String]
11
+ # the human readable time value
12
+ #
13
+ # @api public
14
+ def format_time(time)
15
+ if time >= 100.0
16
+ "%.0f sec" % [time]
17
+ elsif time >= 1.0
18
+ "%.3g sec" % [time]
19
+ elsif time >= 1e-3
20
+ "%.3g ms" % [time * 1e3]
21
+ elsif time >= 1e-6
22
+ "%.3g μs" % [time * 1e6]
23
+ else
24
+ "%.0f ns" % [time * 1e9]
25
+ end
26
+ end
27
+ module_function :format_time
28
+ end # Benchmark
29
+ end # RSpec
@@ -0,0 +1,62 @@
1
+ # encoding: utf-8
2
+
3
+ module RSpec
4
+ module Benchmark
5
+ module IterationMatcher
6
+ # Implements the `perform_at_least` matcher
7
+ #
8
+ # @api private
9
+ class Matcher
10
+ def initialize(iterations, options = {})
11
+ @iterations = iterations
12
+ end
13
+
14
+ # Indicates this matcher matches against a block
15
+ #
16
+ # @return [True]
17
+ #
18
+ # @api private
19
+ def supports_block_expectations?
20
+ true
21
+ end
22
+
23
+ # @return [Boolean]
24
+ #
25
+ # @api private
26
+ def matches?(block)
27
+ @bench = ::Benchmark::Perf::Iteration.new
28
+ @average, @stddev, _ = @bench.run(&block)
29
+ @iterations <= (@average + 3 * @stddev)
30
+ end
31
+
32
+ def ips
33
+ self
34
+ end
35
+
36
+ def failure_message
37
+ "expected block to #{description}, but #{positive_failure_reason}"
38
+ end
39
+
40
+ def failure_message_when_negated
41
+ "expected block not to #{description}, but #{negative_failure_reason}"
42
+ end
43
+
44
+ def description
45
+ "perform at least #{@iterations} i/s"
46
+ end
47
+
48
+ def actual
49
+ "%d (± %d%%) i/s" % [@average, (@stddev / @average.to_f) * 100]
50
+ end
51
+
52
+ def positive_failure_reason
53
+ "performed only #{actual}"
54
+ end
55
+
56
+ def negative_failure_reason
57
+ "performed #{actual}"
58
+ end
59
+ end
60
+ end # IterationMatcher
61
+ end # Benchmark
62
+ end # RSpec
@@ -0,0 +1,53 @@
1
+ # encoding: utf-8
2
+
3
+ require 'rspec/benchmark/timing_matcher'
4
+ require 'rspec/benchmark/iteration_matcher'
5
+
6
+ module RSpec
7
+ module Benchmark
8
+ # Provides a number of useful performance testing expectations
9
+ #
10
+ # These matchers can be exposed by including the this module in
11
+ # a spec:
12
+ #
13
+ # RSpec.describe "Performance testing" do
14
+ # include RSpec::Benchmark::Matchers
15
+ # end
16
+ #
17
+ # or you can include in globablly in a spec_helper.rb file:
18
+ #
19
+ # RSpec.configure do |config|
20
+ # config.inlucde(RSpec::Benchmark::Matchers)
21
+ # end
22
+ #
23
+ # @api public
24
+ module Matchers
25
+ # Passes if code block performs at least iterations
26
+ #
27
+ # @param [Integer] iterations
28
+ #
29
+ # @example
30
+ # expect { ... }.to perform_at_least(10000)
31
+ # expect { ... }.to perform_at_least(10000).ips
32
+ #
33
+ # @api public
34
+ def perform_at_least(iterations, options = {})
35
+ IterationMatcher::Matcher.new(iterations, options)
36
+ end
37
+
38
+ # Passes if code block performs under threshold
39
+ #
40
+ # @param [Float] threshold
41
+ #
42
+ # @example
43
+ # expect { ... }.to peform_under(0.001)
44
+ # expect { ... }.to peform_under(0.001).sec
45
+ # expect { ... }.to peform_under(10).ms
46
+ #
47
+ # @api public
48
+ def perform_under(threshold, options = {})
49
+ TimingMatcher::Matcher.new(threshold, options)
50
+ end
51
+ end # Matchers
52
+ end # Benchmark
53
+ end # RSpec
@@ -0,0 +1,105 @@
1
+ # encoding: utf-8
2
+
3
+ module RSpec
4
+ module Benchmark
5
+ module TimingMatcher
6
+ # Implements the `perform_under` matcher
7
+ #
8
+ # @api private
9
+ class Matcher
10
+ include RSpec::Benchmark
11
+
12
+ attr_reader :threshold
13
+
14
+ def initialize(threshold, options = {})
15
+ @threshold = threshold
16
+ @samples = options.fetch(:samples) { 30 }
17
+ @scale = threshold.to_s.split(/\./).last.size
18
+ @block = nil
19
+ @confidence_interval = nil
20
+ end
21
+
22
+ # Indicates this matcher matches against a block
23
+ #
24
+ # @return [True]
25
+ #
26
+ # @api private
27
+ def supports_block_expectations?
28
+ true
29
+ end
30
+
31
+ # @return [Boolean]
32
+ #
33
+ # @api private
34
+ def matches?(block)
35
+ @block = block
36
+ return false unless block.is_a?(Proc)
37
+ @bench = ::Benchmark::Perf::ExecutionTime.new
38
+ @average, @stddev = @bench.run(@samples, &block)
39
+ @average <= @threshold
40
+ end
41
+
42
+ def does_not_match?(block)
43
+ !matches?(block) && block.is_a?(Proc)
44
+ end
45
+
46
+ def and_sample(samples)
47
+ @samples = samples
48
+ self
49
+ end
50
+
51
+ def secs
52
+ self
53
+ end
54
+ alias_method :sec, :secs
55
+
56
+ # Tell this matcher to convert threshold to ms
57
+ # @api public
58
+ def ms
59
+ @threshold /= 1e3
60
+ self
61
+ end
62
+
63
+ # Tell this matcher to convert threshold to us
64
+ # @api public
65
+ def us
66
+ @threshold /= 1e6
67
+ self
68
+ end
69
+
70
+ # Tell this matcher to convert threshold to ns
71
+ # @api public
72
+ def ns
73
+ @threshold /= 1e9
74
+ self
75
+ end
76
+
77
+ def failure_message
78
+ "expected block to #{description}, but #{positive_failure_reason}"
79
+ end
80
+
81
+ def failure_message_when_negated
82
+ "expected block to not #{description}, but #{negative_failure_reason}"
83
+ end
84
+
85
+ def description
86
+ "perform under #{format_time(@threshold)}"
87
+ end
88
+
89
+ def actual
90
+ "#{format_time(@average)} (± #{format_time(@stddev)})"
91
+ end
92
+
93
+ def positive_failure_reason
94
+ return 'was not a block' unless @block.is_a?(Proc)
95
+ "performed above #{actual} "
96
+ end
97
+
98
+ def negative_failure_reason
99
+ return 'was not a block' unless @block.is_a?(Proc)
100
+ "performed #{actual} under"
101
+ end
102
+ end # Matcher
103
+ end # TiminingMatcher
104
+ end # Benchmark
105
+ end # RSpec
@@ -0,0 +1,7 @@
1
+ # encoding: utf-8
2
+
3
+ module RSpec
4
+ module Benchmark
5
+ VERSION = "0.1.0"
6
+ end # Benchmark
7
+ end # RSpec
@@ -0,0 +1,26 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'rspec/benchmark/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "rspec-benchmark"
8
+ spec.version = RSpec::Benchmark::VERSION
9
+ spec.authors = ["Piotr Murach"]
10
+ spec.email = [""]
11
+ spec.summary = %q{Performance testing matchers for RSpec}
12
+ spec.description = %q{Performance testing matchers for RSpec that provide simple way to specify speed benchmark expectations}
13
+ spec.homepage = ""
14
+ spec.license = "MIT"
15
+
16
+ spec.files = `git ls-files -z`.split("\x0")
17
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
+ spec.test_files = spec.files.grep(%r{^spec/})
19
+ spec.require_paths = ["lib"]
20
+
21
+ spec.add_dependency 'benchmark-perf', '~> 0.1.0'
22
+ spec.add_dependency 'rspec', '>= 3.0.0', '< 4.0.0'
23
+
24
+ spec.add_development_dependency 'bundler', '>= 1.5.0', '< 2.0'
25
+ spec.add_development_dependency 'rake'
26
+ end
@@ -0,0 +1,47 @@
1
+ # encoding: utf-8
2
+
3
+ if RUBY_VERSION > '1.9' and (ENV['COVERAGE'] || ENV['TRAVIS'])
4
+ require 'simplecov'
5
+ require 'coveralls'
6
+
7
+ SimpleCov.formatter = SimpleCov::Formatter::MultiFormatter[
8
+ SimpleCov::Formatter::HTMLFormatter,
9
+ Coveralls::SimpleCov::Formatter
10
+ ]
11
+
12
+ SimpleCov.start do
13
+ command_name 'spec'
14
+ add_filter 'spec'
15
+ end
16
+ end
17
+
18
+ require 'rspec-benchmark'
19
+
20
+ RSpec.configure do |config|
21
+ config.include(RSpec::Benchmark::Matchers)
22
+
23
+ config.expect_with :rspec do |expectations|
24
+ expectations.include_chain_clauses_in_custom_matcher_descriptions = true
25
+ end
26
+
27
+ config.mock_with :rspec do |mocks|
28
+ mocks.verify_partial_doubles = true
29
+ end
30
+
31
+ config.filter_run :focus
32
+ config.run_all_when_everything_filtered = true
33
+
34
+ config.disable_monkey_patching!
35
+
36
+ config.warnings = true
37
+
38
+ if config.files_to_run.one?
39
+ config.default_formatter = 'doc'
40
+ end
41
+
42
+ config.profile_examples = 2
43
+
44
+ config.order = :random
45
+
46
+ Kernel.srand config.seed
47
+ end
@@ -0,0 +1,21 @@
1
+ # encoding: utf-8
2
+
3
+ RSpec.describe RSpec::Benchmark, '#format_time' do
4
+ {
5
+ 1e-10 => "0 ns",
6
+ 0.42e-6 => "420 ns",
7
+ 3.4e-6 => "3.4 μs",
8
+ 34e-6 => "34 μs",
9
+ 340e-6 => "340 μs",
10
+ 1e-3 => "1 ms",
11
+ 12e-3 => "12 ms",
12
+ 1.0 => "1 sec",
13
+ 1.2345 => "1.23 sec",
14
+ 123.45 => "123 sec",
15
+ 1234 => "1234 sec"
16
+ }.each do |input, expected|
17
+ it "#{input} -> #{expected}" do
18
+ expect(described_class.format_time(input)).to eq(expected)
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,34 @@
1
+ # encoding: utf-8
2
+
3
+ RSpec.describe '#perform_at_least' do
4
+
5
+ context "expect { ... }.to perform_at_least(...).ips" do
6
+ it "passes if the block perfoms more than 10K ips" do
7
+ expect {
8
+ 'x' * 1024 * 10
9
+ }.to perform_at_least(10_000).ips
10
+ end
11
+
12
+ it "fails if the block performs less than 10K ips" do
13
+ expect {
14
+ expect {
15
+ 'x' * 1024 * 1024
16
+ }.to perform_at_least(10_000).ips
17
+ }.to raise_error(/expected block to perform at least 10000 i\/s, but performed only \d+ \(± \d+%\) i\/s/)
18
+ end
19
+ end
20
+
21
+ context "expect { ... }.not_to perform_at_least(...).ips" do
22
+ it "passes if the block does not perform more than 10K ips" do
23
+ expect {
24
+ 'x' * 1024 * 1024 * 10
25
+ }.not_to perform_at_least(10_000).ips
26
+ end
27
+
28
+ it "fails if the block performs more than 10K ips" do
29
+ expect {
30
+ expect { 'x' * 1024 }.not_to perform_at_least(10_000).ips
31
+ }.to raise_error(/expected block not to perform at least 10000 i\/s, but performed \d+ \(± \d+%\) i\/s/)
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,53 @@
1
+ # encoding: utf-8
2
+
3
+ RSpec.describe 'RSpec::Benchmark::TimingMatcher', '#perform_under' do
4
+
5
+ context "expect { ... }.to perfom_under(...).and_sample" do
6
+ it "passes if the block performs under threshold" do
7
+ expect {
8
+ 'x' * 1024 * 10
9
+ }.to perform_under(0.006).sec.and_sample(10)
10
+ end
11
+
12
+ it "fails if the block performs above threshold" do
13
+ expect {
14
+ expect {
15
+ 'x' * 1024 * 1024 * 100
16
+ }.to perform_under(0.0001).and_sample(5)
17
+ }.to raise_error(/expected block to perform under 100 μs, but performed above \d+(\.\d+)? ([μmn]s|sec) \(± \d+(\.\d+)? ([μmn]s|sec)\)/)
18
+ end
19
+ end
20
+
21
+ context "expect { ... }.not_to perform_under(...).and_sample" do
22
+ it "passes if the block does not perform under threshold" do
23
+ expect {
24
+ 'x' * 1024 * 1024 * 10
25
+ }.to_not perform_under(0.001).and_sample(2)
26
+ end
27
+
28
+ it "fails if the block perfoms under threshold" do
29
+ expect {
30
+ expect {
31
+ 'x' * 1024 * 1024 * 10
32
+ }.to_not perform_under(1).and_sample(2)
33
+ }.to raise_error(/expected block to not perform under 1 sec, but performed \d+(\.\d+)? ([μmn]s|sec) \(± \d+(\.\d+)? ([μmn]s|sec)\) under/)
34
+ end
35
+ end
36
+
37
+ context 'threshold conversions' do
38
+ it "converts 1ms to sec" do
39
+ matcher = perform_under(1).ms
40
+ expect(matcher.threshold).to eq(0.001)
41
+ end
42
+
43
+ it "converts 1000us to sec" do
44
+ matcher = perform_under(1000).us
45
+ expect(matcher.threshold).to eq(0.001)
46
+ end
47
+
48
+ it "converts ns to sec" do
49
+ matcher = perform_under(100_000).ns
50
+ expect(matcher.threshold).to eq(0.0001)
51
+ end
52
+ end
53
+ end
@@ -0,0 +1,11 @@
1
+ # encoding: utf-8
2
+
3
+ desc 'Measure code coverage'
4
+ task :coverage do
5
+ begin
6
+ original, ENV['COVERAGE'] = ENV['COVERAGE'], 'true'
7
+ Rake::Task['spec'].invoke
8
+ ensure
9
+ ENV['COVERAGE'] = original
10
+ end
11
+ end
@@ -0,0 +1,34 @@
1
+ # encoding: utf-8
2
+
3
+ begin
4
+ require 'rspec/core/rake_task'
5
+
6
+ desc 'Run all specs'
7
+ RSpec::Core::RakeTask.new(:spec) do |task|
8
+ task.pattern = 'spec/{unit,integration}{,/*/**}/*_spec.rb'
9
+ end
10
+
11
+ namespace :spec do
12
+ desc 'Run unit specs'
13
+ RSpec::Core::RakeTask.new(:unit) do |task|
14
+ task.pattern = 'spec/unit{,/*/**}/*_spec.rb'
15
+ end
16
+
17
+ desc 'Run integration specs'
18
+ RSpec::Core::RakeTask.new(:integration) do |task|
19
+ task.pattern = 'spec/integration{,/*/**}/*_spec.rb'
20
+ end
21
+
22
+ desc 'Run performance specs'
23
+ RSpec::Core::RakeTask.new(:perf) do |task|
24
+ task.pattern = 'spec/performance{,/*/**}/*_spec.rb'
25
+ end
26
+ end
27
+
28
+ rescue LoadError
29
+ %w[spec spec:unit spec:integration spec:perf].each do |name|
30
+ task name do
31
+ $stderr.puts "In order to run #{name}, do `gem install rspec`"
32
+ end
33
+ end
34
+ end
metadata ADDED
@@ -0,0 +1,140 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: rspec-benchmark
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Piotr Murach
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2016-01-25 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: benchmark-perf
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ~>
18
+ - !ruby/object:Gem::Version
19
+ version: 0.1.0
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ~>
25
+ - !ruby/object:Gem::Version
26
+ version: 0.1.0
27
+ - !ruby/object:Gem::Dependency
28
+ name: rspec
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - '>='
32
+ - !ruby/object:Gem::Version
33
+ version: 3.0.0
34
+ - - <
35
+ - !ruby/object:Gem::Version
36
+ version: 4.0.0
37
+ type: :runtime
38
+ prerelease: false
39
+ version_requirements: !ruby/object:Gem::Requirement
40
+ requirements:
41
+ - - '>='
42
+ - !ruby/object:Gem::Version
43
+ version: 3.0.0
44
+ - - <
45
+ - !ruby/object:Gem::Version
46
+ version: 4.0.0
47
+ - !ruby/object:Gem::Dependency
48
+ name: bundler
49
+ requirement: !ruby/object:Gem::Requirement
50
+ requirements:
51
+ - - '>='
52
+ - !ruby/object:Gem::Version
53
+ version: 1.5.0
54
+ - - <
55
+ - !ruby/object:Gem::Version
56
+ version: '2.0'
57
+ type: :development
58
+ prerelease: false
59
+ version_requirements: !ruby/object:Gem::Requirement
60
+ requirements:
61
+ - - '>='
62
+ - !ruby/object:Gem::Version
63
+ version: 1.5.0
64
+ - - <
65
+ - !ruby/object:Gem::Version
66
+ version: '2.0'
67
+ - !ruby/object:Gem::Dependency
68
+ name: rake
69
+ requirement: !ruby/object:Gem::Requirement
70
+ requirements:
71
+ - - '>='
72
+ - !ruby/object:Gem::Version
73
+ version: '0'
74
+ type: :development
75
+ prerelease: false
76
+ version_requirements: !ruby/object:Gem::Requirement
77
+ requirements:
78
+ - - '>='
79
+ - !ruby/object:Gem::Version
80
+ version: '0'
81
+ description: Performance testing matchers for RSpec that provide simple way to specify
82
+ speed benchmark expectations
83
+ email:
84
+ - ''
85
+ executables: []
86
+ extensions: []
87
+ extra_rdoc_files: []
88
+ files:
89
+ - .gitignore
90
+ - .rspec
91
+ - .travis.yml
92
+ - CHANGELOG.md
93
+ - Gemfile
94
+ - LICENSE.txt
95
+ - README.md
96
+ - Rakefile
97
+ - lib/rspec-benchmark.rb
98
+ - lib/rspec/benchmark.rb
99
+ - lib/rspec/benchmark/format_time.rb
100
+ - lib/rspec/benchmark/iteration_matcher.rb
101
+ - lib/rspec/benchmark/matchers.rb
102
+ - lib/rspec/benchmark/timing_matcher.rb
103
+ - lib/rspec/benchmark/version.rb
104
+ - rspec-benchmark.gemspec
105
+ - spec/spec_helper.rb
106
+ - spec/unit/format_time_spec.rb
107
+ - spec/unit/perform_at_least_spec.rb
108
+ - spec/unit/perform_under_spec.rb
109
+ - tasks/coverage.rake
110
+ - tasks/spec.rake
111
+ homepage: ''
112
+ licenses:
113
+ - MIT
114
+ metadata: {}
115
+ post_install_message:
116
+ rdoc_options: []
117
+ require_paths:
118
+ - lib
119
+ required_ruby_version: !ruby/object:Gem::Requirement
120
+ requirements:
121
+ - - '>='
122
+ - !ruby/object:Gem::Version
123
+ version: '0'
124
+ required_rubygems_version: !ruby/object:Gem::Requirement
125
+ requirements:
126
+ - - '>='
127
+ - !ruby/object:Gem::Version
128
+ version: '0'
129
+ requirements: []
130
+ rubyforge_project:
131
+ rubygems_version: 2.0.3
132
+ signing_key:
133
+ specification_version: 4
134
+ summary: Performance testing matchers for RSpec
135
+ test_files:
136
+ - spec/spec_helper.rb
137
+ - spec/unit/format_time_spec.rb
138
+ - spec/unit/perform_at_least_spec.rb
139
+ - spec/unit/perform_under_spec.rb
140
+ has_rdoc: