rspec-benchmark 0.3.0 → 0.4.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 +5 -5
- data/CHANGELOG.md +20 -0
- data/README.md +119 -22
- data/lib/rspec/benchmark.rb +3 -6
- data/lib/rspec/benchmark/comparison_matcher.rb +31 -7
- data/lib/rspec/benchmark/complexity_matcher.rb +89 -0
- data/lib/rspec/benchmark/format_time.rb +1 -1
- data/lib/rspec/benchmark/iteration_matcher.rb +31 -5
- data/lib/rspec/benchmark/matchers.rb +83 -4
- data/lib/rspec/benchmark/timing_matcher.rb +35 -9
- data/lib/rspec/benchmark/version.rb +2 -2
- data/rspec-benchmark.gemspec +10 -6
- data/spec/spec_helper.rb +6 -16
- data/spec/unit/comparison_matcher_spec.rb +27 -6
- data/spec/unit/composable_spec.rb +9 -0
- data/spec/unit/perform_at_least_spec.rb +6 -6
- data/spec/unit/perform_constant_spec.rb +46 -0
- data/spec/unit/perform_exponential_spec.rb +42 -0
- data/spec/unit/perform_linear_spec.rb +72 -0
- data/spec/unit/perform_logarithmic_spec.rb +49 -0
- data/spec/unit/perform_power_spec.rb +55 -0
- data/spec/unit/perform_under_spec.rb +17 -11
- metadata +40 -24
- data/.gitignore +0 -14
- data/.rspec +0 -2
- data/.travis.yml +0 -28
- data/Gemfile +0 -9
@@ -0,0 +1,72 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
RSpec.describe 'RSpec::Benchmark::ComplexityMatcher', '#perform_linear' do
|
4
|
+
# exponential
|
5
|
+
def fibonacci(n)
|
6
|
+
n < 2 ? n : fibonacci(n - 1) + fibonacci(n - 2)
|
7
|
+
end
|
8
|
+
|
9
|
+
it "propagates error inside expectation" do
|
10
|
+
expect {
|
11
|
+
expect { raise 'boom' }.to perform_linear
|
12
|
+
}.to raise_error(StandardError, /boom/)
|
13
|
+
end
|
14
|
+
|
15
|
+
it "provides a default range" do
|
16
|
+
range = [1,2,3]
|
17
|
+
allow(::Benchmark::Trend).to receive(:range).and_return(range)
|
18
|
+
allow(::Benchmark::Trend).to receive(:infer_trend).and_return(:linear, {})
|
19
|
+
|
20
|
+
expect { |n, i| n }.to perform_linear
|
21
|
+
|
22
|
+
expect(::Benchmark::Trend).to have_received(:range).with(8, 8192, ratio: 8)
|
23
|
+
end
|
24
|
+
|
25
|
+
it "changes default range using in_range and ratio matchers" do
|
26
|
+
range = [1,2,3]
|
27
|
+
allow(::Benchmark::Trend).to receive(:range).and_return(range)
|
28
|
+
allow(::Benchmark::Trend).to receive(:infer_trend).and_return(:linear, {})
|
29
|
+
|
30
|
+
expect { |n, i| n }.to perform_linear.in_range(3, 33_000).ratio(2)
|
31
|
+
|
32
|
+
expect(::Benchmark::Trend).to have_received(:range).with(3, 33_000, ratio: 2)
|
33
|
+
end
|
34
|
+
|
35
|
+
context "expect { ... }.to perfom_linear" do
|
36
|
+
it "passes if the block performs linear" do
|
37
|
+
range = bench_range(1, 8 << 10)
|
38
|
+
numbers = range.map { |n| Array.new(n) { rand(n) } }
|
39
|
+
|
40
|
+
expect { |n, i|
|
41
|
+
numbers[i].max
|
42
|
+
}.to perform_linear.in_range(range[0], range[-1]).sample(100)
|
43
|
+
end
|
44
|
+
|
45
|
+
it "fails if the block doesn't perform linear" do
|
46
|
+
expect {
|
47
|
+
expect { |n, i|
|
48
|
+
fibonacci(n)
|
49
|
+
}.to perform_linear.in_range(1, 18).ratio(2).sample(100)
|
50
|
+
}.to raise_error("expected block to perform linear, but performed exponential")
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
context "expect { ... }.not_to perfom_linear" do
|
55
|
+
it "passes if the block does not perform linear" do
|
56
|
+
expect { |n, i|
|
57
|
+
fibonacci(n)
|
58
|
+
}.not_to perform_linear.in_range(1, 18).ratio(2).sample(100)
|
59
|
+
end
|
60
|
+
|
61
|
+
it "fails if the block doesn't perform linear" do
|
62
|
+
range = bench_range(10, 8 << 12)
|
63
|
+
numbers = range.map { |n| Array.new(n) { rand(n) } }
|
64
|
+
|
65
|
+
expect {
|
66
|
+
expect { |n, i|
|
67
|
+
numbers[i].max
|
68
|
+
}.not_to perform_linear.in_range(range[0], range[-1]).sample(100)
|
69
|
+
}.to raise_error("expected block not to perform linear, but performed linear")
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
RSpec.describe 'RSpec::Benchmark::ComplexityMatcher', '#perform_logarithmic' do
|
4
|
+
# Iterated logarithm
|
5
|
+
# https://en.wikipedia.org/wiki/Iterated_logarithm
|
6
|
+
def log_star(n, repeat = 0)
|
7
|
+
n <= 1 ? repeat : 1 + log_star(Math.log(n), repeat += 1)
|
8
|
+
end
|
9
|
+
|
10
|
+
it "propagates error inside expectation" do
|
11
|
+
expect {
|
12
|
+
expect { raise 'boom' }.to perform_logarithmic
|
13
|
+
}.to raise_error(StandardError, /boom/)
|
14
|
+
end
|
15
|
+
|
16
|
+
context "expect { ... }.to perfom_logarithmic" do
|
17
|
+
xit "passes if the block performs logarithmic" do
|
18
|
+
range = bench_range(1, 8 << 18, ratio: 2)
|
19
|
+
numbers = range.map { |n| (1..n).to_a }
|
20
|
+
|
21
|
+
expect { |n, i|
|
22
|
+
numbers[i].bsearch { |x| x == 1 }
|
23
|
+
}.to perform_logarithmic.in_range(range[0], range[-1]).ratio(2).sample(100).times
|
24
|
+
end
|
25
|
+
|
26
|
+
it "fails if the block doesn't perform logarithmic" do
|
27
|
+
expect {
|
28
|
+
expect { |n| n }.to perform_logarithmic.in_range(1, 10_000).sample(100)
|
29
|
+
}.to raise_error("expected block to perform logarithmic, but performed constant")
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
context "expect { ... }.not_to perfom_logarithmic" do
|
34
|
+
it "passes if the block does not perform logarithmic" do
|
35
|
+
expect { |n| n }.not_to perform_logarithmic.in_range(1, 10_000).sample(100)
|
36
|
+
end
|
37
|
+
|
38
|
+
xit "fails if the block doesn't perform logarithmic" do
|
39
|
+
range = bench_range(1, 8 << 18, ratio: 2)
|
40
|
+
numbers = range.map { |n| (1..n).to_a }
|
41
|
+
|
42
|
+
expect {
|
43
|
+
expect { |n, i|
|
44
|
+
numbers[i].bsearch { |x| x == 1 }
|
45
|
+
}.not_to perform_logarithmic.in_range(range[0], range[-1]).ratio(2).sample(100).times
|
46
|
+
}.to raise_error("expected block not to perform logarithmic, but performed logarithmic")
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
@@ -0,0 +1,55 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
RSpec.describe 'RSpec::Benchmark::ComplexityMatcher', '#perform_power' do
|
4
|
+
def prefix_avg(numbers)
|
5
|
+
result = []
|
6
|
+
numbers.each_with_index do |i, num|
|
7
|
+
sum = 0.0
|
8
|
+
numbers[0..i].each do |a|
|
9
|
+
sum += a
|
10
|
+
end
|
11
|
+
result[i] = sum / i
|
12
|
+
end
|
13
|
+
result
|
14
|
+
end
|
15
|
+
|
16
|
+
it "propagates error inside expectation" do
|
17
|
+
expect {
|
18
|
+
expect { raise 'boom' }.to perform_power
|
19
|
+
}.to raise_error(StandardError, /boom/)
|
20
|
+
end
|
21
|
+
|
22
|
+
context "expect { ... }.to perfom_power" do
|
23
|
+
it "passes if the block performs power" do
|
24
|
+
range = bench_range(10, 8 << 5)
|
25
|
+
numbers = range.map { |n| Array.new(n) { rand(n) } }
|
26
|
+
|
27
|
+
expect { |n, i|
|
28
|
+
prefix_avg(numbers[i])
|
29
|
+
}.to perform_power.in_range(range[0], range[-1]).sample(100).times
|
30
|
+
end
|
31
|
+
|
32
|
+
it "fails if the block doesn't perform power" do
|
33
|
+
expect {
|
34
|
+
expect { |n| n }.to perform_power.in_range(1, 10_000).sample(100)
|
35
|
+
}.to raise_error("expected block to perform power, but performed constant")
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
context "expect { ... }.not_to perfom_power" do
|
40
|
+
it "passes if the block does not perform power" do
|
41
|
+
expect { |n| n }.not_to perform_power.in_range(1, 10_000).sample(100)
|
42
|
+
end
|
43
|
+
|
44
|
+
it "fails if the block doesn't perform power" do
|
45
|
+
range = bench_range(10, 8 << 5)
|
46
|
+
numbers = range.map { |n| Array.new(n) { rand(n) } }
|
47
|
+
|
48
|
+
expect {
|
49
|
+
expect { |n, i|
|
50
|
+
prefix_avg(numbers[i])
|
51
|
+
}.not_to perform_power.in_range(range[0], range[-1]).sample(100).times
|
52
|
+
}.to raise_error("expected block not to perform power, but performed power")
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
@@ -1,4 +1,4 @@
|
|
1
|
-
#
|
1
|
+
# frozen_string_literal: true
|
2
2
|
|
3
3
|
RSpec.describe 'RSpec::Benchmark::TimingMatcher', '#perform_under' do
|
4
4
|
it "propagates error inside expectation" do
|
@@ -8,40 +8,46 @@ RSpec.describe 'RSpec::Benchmark::TimingMatcher', '#perform_under' do
|
|
8
8
|
end
|
9
9
|
|
10
10
|
it "allows to configure warmup cycles" do
|
11
|
-
bench =
|
12
|
-
allow(::Benchmark::Perf::ExecutionTime).to receive(:
|
13
|
-
expect { 'x' * 1024 * 10 }.to perform_under(0.006
|
14
|
-
expect(::Benchmark::Perf::ExecutionTime).to have_received(:
|
11
|
+
bench = [0.005, 0.00001]
|
12
|
+
allow(::Benchmark::Perf::ExecutionTime).to receive(:run).and_return(bench)
|
13
|
+
expect { 'x' * 1024 * 10 }.to perform_under(0.006).sec.warmup(2).times.sample(3)
|
14
|
+
expect(::Benchmark::Perf::ExecutionTime).to have_received(:run).with(repeat: 3, warmup: 2)
|
15
15
|
end
|
16
16
|
|
17
|
-
|
17
|
+
it "doesn't allow sample size less than 1" do
|
18
|
+
expect {
|
19
|
+
expect { 'x' * 1024 * 10 }.to perform_under(0.006).sec.sample(0)
|
20
|
+
}.to raise_error(/Repeat value: 0 needs to be greater than 0/)
|
21
|
+
end
|
22
|
+
|
23
|
+
context "expect { ... }.to perfom_under(...).sample" do
|
18
24
|
it "passes if the block performs under threshold" do
|
19
25
|
expect {
|
20
26
|
'x' * 1024 * 10
|
21
|
-
}.to perform_under(0.006).sec.
|
27
|
+
}.to perform_under(0.006).sec.sample(10).times
|
22
28
|
end
|
23
29
|
|
24
30
|
it "fails if the block performs above threshold" do
|
25
31
|
expect {
|
26
32
|
expect {
|
27
33
|
'x' * 1024 * 1024 * 100
|
28
|
-
}.to perform_under(0.0001).
|
34
|
+
}.to perform_under(0.0001).sample(5)
|
29
35
|
}.to raise_error(/expected block to perform under 100 μs, but performed above \d+(\.\d+)? ([μmn]s|sec) \(± \d+(\.\d+)? ([μmn]s|sec)\)/)
|
30
36
|
end
|
31
37
|
end
|
32
38
|
|
33
|
-
context "expect { ... }.not_to perform_under(...).
|
39
|
+
context "expect { ... }.not_to perform_under(...).sample" do
|
34
40
|
it "passes if the block does not perform under threshold" do
|
35
41
|
expect {
|
36
42
|
'x' * 1024 * 1024 * 10
|
37
|
-
}.to_not perform_under(0.001).
|
43
|
+
}.to_not perform_under(0.001).sample(2)
|
38
44
|
end
|
39
45
|
|
40
46
|
it "fails if the block perfoms under threshold" do
|
41
47
|
expect {
|
42
48
|
expect {
|
43
49
|
'x' * 1024 * 1024 * 10
|
44
|
-
}.to_not perform_under(1).
|
50
|
+
}.to_not perform_under(1).sample(2)
|
45
51
|
}.to raise_error(/expected block to not perform under 1 sec, but performed \d+(\.\d+)? ([μmn]s|sec) \(± \d+(\.\d+)? ([μmn]s|sec)\) under/)
|
46
52
|
end
|
47
53
|
end
|
metadata
CHANGED
@@ -1,17 +1,31 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rspec-benchmark
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.4.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: 2018-10-01 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: benchmark-perf
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: 0.4.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.4.0
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: benchmark-trend
|
15
29
|
requirement: !ruby/object:Gem::Requirement
|
16
30
|
requirements:
|
17
31
|
- - "~>"
|
@@ -48,55 +62,46 @@ dependencies:
|
|
48
62
|
name: bundler
|
49
63
|
requirement: !ruby/object:Gem::Requirement
|
50
64
|
requirements:
|
51
|
-
- - "
|
52
|
-
- !ruby/object:Gem::Version
|
53
|
-
version: 1.5.0
|
54
|
-
- - "<"
|
65
|
+
- - "~>"
|
55
66
|
- !ruby/object:Gem::Version
|
56
|
-
version: '
|
67
|
+
version: '1.16'
|
57
68
|
type: :development
|
58
69
|
prerelease: false
|
59
70
|
version_requirements: !ruby/object:Gem::Requirement
|
60
71
|
requirements:
|
61
|
-
- - "
|
62
|
-
- !ruby/object:Gem::Version
|
63
|
-
version: 1.5.0
|
64
|
-
- - "<"
|
72
|
+
- - "~>"
|
65
73
|
- !ruby/object:Gem::Version
|
66
|
-
version: '
|
74
|
+
version: '1.16'
|
67
75
|
- !ruby/object:Gem::Dependency
|
68
76
|
name: rake
|
69
77
|
requirement: !ruby/object:Gem::Requirement
|
70
78
|
requirements:
|
71
|
-
- - "
|
79
|
+
- - "~>"
|
72
80
|
- !ruby/object:Gem::Version
|
73
|
-
version: '0'
|
81
|
+
version: '10.0'
|
74
82
|
type: :development
|
75
83
|
prerelease: false
|
76
84
|
version_requirements: !ruby/object:Gem::Requirement
|
77
85
|
requirements:
|
78
|
-
- - "
|
86
|
+
- - "~>"
|
79
87
|
- !ruby/object:Gem::Version
|
80
|
-
version: '0'
|
88
|
+
version: '10.0'
|
81
89
|
description: Performance testing matchers for RSpec that provide simple way to specify
|
82
|
-
speed benchmark expectations
|
90
|
+
speed and algorithmic complexity benchmark expectations
|
83
91
|
email:
|
84
92
|
- ''
|
85
93
|
executables: []
|
86
94
|
extensions: []
|
87
95
|
extra_rdoc_files: []
|
88
96
|
files:
|
89
|
-
- ".gitignore"
|
90
|
-
- ".rspec"
|
91
|
-
- ".travis.yml"
|
92
97
|
- CHANGELOG.md
|
93
|
-
- Gemfile
|
94
98
|
- LICENSE.txt
|
95
99
|
- README.md
|
96
100
|
- Rakefile
|
97
101
|
- lib/rspec-benchmark.rb
|
98
102
|
- lib/rspec/benchmark.rb
|
99
103
|
- lib/rspec/benchmark/comparison_matcher.rb
|
104
|
+
- lib/rspec/benchmark/complexity_matcher.rb
|
100
105
|
- lib/rspec/benchmark/format_time.rb
|
101
106
|
- lib/rspec/benchmark/iteration_matcher.rb
|
102
107
|
- lib/rspec/benchmark/matchers.rb
|
@@ -105,8 +110,14 @@ files:
|
|
105
110
|
- rspec-benchmark.gemspec
|
106
111
|
- spec/spec_helper.rb
|
107
112
|
- spec/unit/comparison_matcher_spec.rb
|
113
|
+
- spec/unit/composable_spec.rb
|
108
114
|
- spec/unit/format_time_spec.rb
|
109
115
|
- spec/unit/perform_at_least_spec.rb
|
116
|
+
- spec/unit/perform_constant_spec.rb
|
117
|
+
- spec/unit/perform_exponential_spec.rb
|
118
|
+
- spec/unit/perform_linear_spec.rb
|
119
|
+
- spec/unit/perform_logarithmic_spec.rb
|
120
|
+
- spec/unit/perform_power_spec.rb
|
110
121
|
- spec/unit/perform_under_spec.rb
|
111
122
|
- tasks/coverage.rake
|
112
123
|
- tasks/spec.rake
|
@@ -122,7 +133,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
122
133
|
requirements:
|
123
134
|
- - ">="
|
124
135
|
- !ruby/object:Gem::Version
|
125
|
-
version:
|
136
|
+
version: 2.0.0
|
126
137
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
127
138
|
requirements:
|
128
139
|
- - ">="
|
@@ -130,14 +141,19 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
130
141
|
version: '0'
|
131
142
|
requirements: []
|
132
143
|
rubyforge_project:
|
133
|
-
rubygems_version: 2.
|
144
|
+
rubygems_version: 2.7.3
|
134
145
|
signing_key:
|
135
146
|
specification_version: 4
|
136
147
|
summary: Performance testing matchers for RSpec
|
137
148
|
test_files:
|
138
149
|
- spec/spec_helper.rb
|
139
150
|
- spec/unit/comparison_matcher_spec.rb
|
151
|
+
- spec/unit/composable_spec.rb
|
140
152
|
- spec/unit/format_time_spec.rb
|
141
153
|
- spec/unit/perform_at_least_spec.rb
|
154
|
+
- spec/unit/perform_constant_spec.rb
|
155
|
+
- spec/unit/perform_exponential_spec.rb
|
156
|
+
- spec/unit/perform_linear_spec.rb
|
157
|
+
- spec/unit/perform_logarithmic_spec.rb
|
158
|
+
- spec/unit/perform_power_spec.rb
|
142
159
|
- spec/unit/perform_under_spec.rb
|
143
|
-
has_rdoc:
|
data/.gitignore
DELETED
data/.rspec
DELETED
data/.travis.yml
DELETED
@@ -1,28 +0,0 @@
|
|
1
|
-
---
|
2
|
-
language: ruby
|
3
|
-
sudo: false
|
4
|
-
cache: bundler
|
5
|
-
script: "bundle exec rake ci"
|
6
|
-
rvm:
|
7
|
-
- 2.0.0
|
8
|
-
- 2.1.10
|
9
|
-
- 2.2.6
|
10
|
-
- 2.3.3
|
11
|
-
- 2.4.0
|
12
|
-
- ruby-head
|
13
|
-
- jruby-9000
|
14
|
-
- jruby-head
|
15
|
-
- rbx-3
|
16
|
-
env:
|
17
|
-
global:
|
18
|
-
- JRUBY_OPTS="-Xcli.debug=true --debug"
|
19
|
-
matrix:
|
20
|
-
allow_failures:
|
21
|
-
- rvm: rbx-3
|
22
|
-
- rvm: ruby-head
|
23
|
-
- rvm: jruby-head
|
24
|
-
fast_finish: true
|
25
|
-
branches:
|
26
|
-
only: master
|
27
|
-
notifications:
|
28
|
-
email: false
|