rspec-benchmark 0.5.1 → 0.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +18 -0
- data/README.md +14 -1
- data/lib/rspec-benchmark.rb +1 -1
- data/lib/rspec/benchmark.rb +3 -3
- data/lib/rspec/benchmark/allocation_matcher.rb +6 -6
- data/lib/rspec/benchmark/comparison_matcher.rb +4 -4
- data/lib/rspec/benchmark/configuration.rb +8 -0
- data/lib/rspec/benchmark/formatter.rb +51 -0
- data/lib/rspec/benchmark/iteration_matcher.rb +18 -5
- data/lib/rspec/benchmark/matchers.rb +16 -16
- data/lib/rspec/benchmark/timing_matcher.rb +13 -13
- data/lib/rspec/benchmark/version.rb +1 -1
- metadata +21 -66
- data/Rakefile +0 -10
- data/lib/rspec/benchmark/format_time.rb +0 -29
- data/rspec-benchmark.gemspec +0 -37
- data/spec/spec_helper.rb +0 -37
- data/spec/unit/comparison_matcher_spec.rb +0 -212
- data/spec/unit/composable_spec.rb +0 -9
- data/spec/unit/configuration_spec.rb +0 -84
- data/spec/unit/format_time_spec.rb +0 -21
- data/spec/unit/perform_allocation_spec.rb +0 -128
- data/spec/unit/perform_at_least_spec.rb +0 -45
- data/spec/unit/perform_constant_spec.rb +0 -46
- data/spec/unit/perform_exponential_spec.rb +0 -42
- data/spec/unit/perform_linear_spec.rb +0 -80
- data/spec/unit/perform_logarithmic_spec.rb +0 -49
- data/spec/unit/perform_power_spec.rb +0 -55
- data/spec/unit/perform_under_spec.rb +0 -74
- data/tasks/coverage.rake +0 -11
- data/tasks/spec.rake +0 -34
@@ -1,84 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
RSpec.describe RSpec::Benchmark do
|
4
|
-
after(:example) do
|
5
|
-
RSpec::Benchmark.reset_configuration
|
6
|
-
end
|
7
|
-
|
8
|
-
it "defaults :run_in_subprocess option to false" do
|
9
|
-
config = RSpec::Benchmark.configuration
|
10
|
-
|
11
|
-
expect(config.run_in_subprocess).to eq(false)
|
12
|
-
end
|
13
|
-
|
14
|
-
it "defaults :disable_gc option to false" do
|
15
|
-
config = RSpec::Benchmark.configuration
|
16
|
-
|
17
|
-
expect(config.disable_gc).to eq(false)
|
18
|
-
end
|
19
|
-
|
20
|
-
it "defaults :samples option to 1" do
|
21
|
-
config = RSpec::Benchmark.configuration
|
22
|
-
|
23
|
-
expect(config.samples).to eq(1)
|
24
|
-
end
|
25
|
-
|
26
|
-
it "sets :run_in_subprocess option to true" do
|
27
|
-
RSpec::Benchmark.configure do |config|
|
28
|
-
config.run_in_subprocess = true
|
29
|
-
end
|
30
|
-
|
31
|
-
config = RSpec::Benchmark.configuration
|
32
|
-
|
33
|
-
expect(config.run_in_subprocess).to eq(true)
|
34
|
-
end
|
35
|
-
|
36
|
-
it "sets :disable_gc option to true" do
|
37
|
-
RSpec::Benchmark.configure do |config|
|
38
|
-
config.disable_gc = true
|
39
|
-
end
|
40
|
-
|
41
|
-
config = RSpec::Benchmark.configuration
|
42
|
-
|
43
|
-
expect(config.disable_gc).to eq(true)
|
44
|
-
end
|
45
|
-
|
46
|
-
it "sets :samples option to 10" do
|
47
|
-
RSpec::Benchmark.configure do |config|
|
48
|
-
config.samples = 10
|
49
|
-
end
|
50
|
-
|
51
|
-
config = RSpec::Benchmark.configuration
|
52
|
-
|
53
|
-
expect(config.samples).to eq(10)
|
54
|
-
end
|
55
|
-
|
56
|
-
it "uses the :run_in_subprocess option in timing matcher" do
|
57
|
-
RSpec::Benchmark.configure do |config|
|
58
|
-
config.run_in_subprocess = true
|
59
|
-
config.samples = 10
|
60
|
-
end
|
61
|
-
|
62
|
-
bench = [0.005, 0.00001]
|
63
|
-
allow(::Benchmark::Perf::ExecutionTime).to receive(:run).and_return(bench)
|
64
|
-
|
65
|
-
expect { 'x' * 1024 }.to perform_under(0.1)
|
66
|
-
|
67
|
-
expect(::Benchmark::Perf::ExecutionTime).to have_received(:run).with(
|
68
|
-
subprocess: true, warmup: 1, repeat: 10)
|
69
|
-
end
|
70
|
-
|
71
|
-
it "uses the :samples option in complexity matcher" do
|
72
|
-
RSpec::Benchmark.configure do |config|
|
73
|
-
config.samples = 10
|
74
|
-
end
|
75
|
-
|
76
|
-
bench = [:constant, {constant: {residual: 0.9}}]
|
77
|
-
allow(::Benchmark::Trend).to receive(:infer_trend).and_return(bench)
|
78
|
-
|
79
|
-
expect { 'x' * 1024 }.to perform_constant
|
80
|
-
|
81
|
-
expect(::Benchmark::Trend).to have_received(:infer_trend).with(
|
82
|
-
[8, 64, 512, 4096, 8192], repeat: 10)
|
83
|
-
end
|
84
|
-
end
|
@@ -1,21 +0,0 @@
|
|
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
|
@@ -1,128 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
RSpec.describe "#perform_allocation" do
|
4
|
-
context "expect { ... }.to perform_allocation(...)" do
|
5
|
-
it "passes if the block performs allocations" do
|
6
|
-
expect {
|
7
|
-
_a = [Object.new]
|
8
|
-
}.to perform_allocation(2)
|
9
|
-
end
|
10
|
-
|
11
|
-
it "fails if the block doesn't perform allocation(...)" do
|
12
|
-
expect {
|
13
|
-
expect {
|
14
|
-
_a = [Object.new]
|
15
|
-
}.to perform_allocation(1)
|
16
|
-
}.to raise_error(/expected block to perform allocation of \d object, but allocated \d objects/)
|
17
|
-
end
|
18
|
-
end
|
19
|
-
|
20
|
-
context "expect { ... }.not_to perform_allocation(...)" do
|
21
|
-
it "passes if the block does not perform allocation" do
|
22
|
-
expect {
|
23
|
-
["foo", "bar", "baz"].sort[1]
|
24
|
-
}.to_not perform_allocation(2)
|
25
|
-
end
|
26
|
-
|
27
|
-
it "fails if the block performs allocation" do
|
28
|
-
expect {
|
29
|
-
expect {
|
30
|
-
_a = [Object.new]
|
31
|
-
}.to_not perform_allocation(2)
|
32
|
-
}.to raise_error(/expected block not to perform allocation of \d objects, but allocated \d objects/)
|
33
|
-
end
|
34
|
-
end
|
35
|
-
|
36
|
-
context "expect { ... }.to perform_allocation(Object => ???, ...).objects" do
|
37
|
-
it "splits object allocations by count" do
|
38
|
-
expect {
|
39
|
-
_a = [Object.new]
|
40
|
-
_b = {Object.new => 'foo'}
|
41
|
-
}.to perform_allocation({Object => 2, Array => 1}).objects
|
42
|
-
end
|
43
|
-
|
44
|
-
it "fails to split object allocations by count" do
|
45
|
-
expect {
|
46
|
-
expect {
|
47
|
-
_a = [Object.new]
|
48
|
-
_b = {Object.new => 'bar'}
|
49
|
-
}.to perform_allocation({Object => 1, Array => 1}).objects
|
50
|
-
}.to raise_error("expected block to perform allocation of 1 Array and 1 Object objects, but allocated 1 Array and 2 Object objects")
|
51
|
-
end
|
52
|
-
end
|
53
|
-
|
54
|
-
context "expect { ... }.not_to perform_allocation(Object => ???, ...).objects" do
|
55
|
-
it "passes if the split of object allocations by count is wrong" do
|
56
|
-
expect {
|
57
|
-
_a = [Object.new]
|
58
|
-
_b = {Object.new => 'foo'}
|
59
|
-
}.to_not perform_allocation({Object => 1, Array => 1}).objects
|
60
|
-
end
|
61
|
-
|
62
|
-
it "fails to split object allocations by count" do
|
63
|
-
expect {
|
64
|
-
expect {
|
65
|
-
_a = [Object.new]
|
66
|
-
_b = {Object.new => 'bar'}
|
67
|
-
}.to_not perform_allocation({Object => 2, Array => 1}).objects
|
68
|
-
}.to raise_error("expected block not to perform allocation of 1 Array and 2 Object objects, but allocated 1 Array and 2 Object objects")
|
69
|
-
end
|
70
|
-
end
|
71
|
-
|
72
|
-
context "expect { ... }.to perform_allocation(...).bytes" do
|
73
|
-
it "passes if the block performs allocations" do
|
74
|
-
expect {
|
75
|
-
_a = [Object.new]
|
76
|
-
_b = {Object.new => 'foo'}
|
77
|
-
}.to perform_allocation(600).bytes
|
78
|
-
end
|
79
|
-
|
80
|
-
it "fails if the block doesn't perform allocation" do
|
81
|
-
expect {
|
82
|
-
expect {
|
83
|
-
_a = {Object.new => 'foo'}
|
84
|
-
}.to perform_allocation(10).bytes
|
85
|
-
}.to raise_error(/expected block to perform allocation of \d+ bytes, but allocated \d+ bytes/)
|
86
|
-
end
|
87
|
-
end
|
88
|
-
|
89
|
-
context "expect { ... }.not_to perform_allocation(...).bytes" do
|
90
|
-
it "passes if the block does not perform allocation" do
|
91
|
-
expect {
|
92
|
-
_a = {Object.new => 'foo'}
|
93
|
-
}.to_not perform_allocation(10).bytes
|
94
|
-
end
|
95
|
-
|
96
|
-
it "fails if the block performs allocation" do
|
97
|
-
expect {
|
98
|
-
expect {
|
99
|
-
_a = [Object.new]
|
100
|
-
}.to_not perform_allocation(200).bytes
|
101
|
-
}.to raise_error(/expected block not to perform allocation of \d+ bytes, but allocated \d+ bytes/)
|
102
|
-
end
|
103
|
-
end
|
104
|
-
|
105
|
-
context "expect { ... }.to perform_allocation(Object => ???, ...).bytes" do
|
106
|
-
it "splits object allocations by memory size" do
|
107
|
-
expect {
|
108
|
-
_a = [Object.new]
|
109
|
-
_b = {Object.new => 'foo'}
|
110
|
-
}.to perform_allocation({Object => 80, Array => 40, Hash => 500}).bytes
|
111
|
-
end
|
112
|
-
|
113
|
-
it "fails to split object allocations by memory size" do
|
114
|
-
expect {
|
115
|
-
expect {
|
116
|
-
_a = [Object.new]
|
117
|
-
_b = {Object.new => 'bar'}
|
118
|
-
}.to perform_allocation({Object => 80, Hash => 0}).bytes
|
119
|
-
}.to raise_error(/expected block to perform allocation of \d+ Hash and \d+ Object bytes, but allocated \d+ Hash and \d+ Object bytes/)
|
120
|
-
end
|
121
|
-
end
|
122
|
-
|
123
|
-
it "fails to recognize expectation type" do
|
124
|
-
expect {
|
125
|
-
expect { Object.new }.to perform_allocation(:error)
|
126
|
-
}.to raise_error(ArgumentError, "'error' is not a recognized argument")
|
127
|
-
end
|
128
|
-
end
|
@@ -1,45 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
RSpec.describe '#perform_at_least' do
|
4
|
-
it "allows to configure matcher timings" do
|
5
|
-
bench = [10_000, 100]
|
6
|
-
allow(::Benchmark::Perf::Iteration).to receive(:run).and_return(bench)
|
7
|
-
|
8
|
-
expect {
|
9
|
-
'x' * 1024 * 10
|
10
|
-
}.to perform_at_least(10_000).within(0.3).warmup(0.2)
|
11
|
-
|
12
|
-
expect(::Benchmark::Perf::Iteration).to have_received(:run).
|
13
|
-
with(time: 0.3, warmup: 0.2)
|
14
|
-
end
|
15
|
-
|
16
|
-
context "expect { ... }.to perform_at_least(...).ips" do
|
17
|
-
it "passes if the block perfoms more than 10K ips" do
|
18
|
-
expect {
|
19
|
-
'x' * 1024 * 10
|
20
|
-
}.to perform_at_least(10_000).ips
|
21
|
-
end
|
22
|
-
|
23
|
-
it "fails if the block performs less than 10K ips" do
|
24
|
-
expect {
|
25
|
-
expect {
|
26
|
-
'x' * 1024 * 1024
|
27
|
-
}.to perform_at_least(10_000).ips
|
28
|
-
}.to raise_error(/expected block to perform at least 10000 i\/s, but performed only \d+ \(± \d+%\) i\/s/)
|
29
|
-
end
|
30
|
-
end
|
31
|
-
|
32
|
-
context "expect { ... }.not_to perform_at_least(...).ips" do
|
33
|
-
it "passes if the block does not perform more than 10K ips" do
|
34
|
-
expect {
|
35
|
-
'x' * 1024 * 1024 * 10
|
36
|
-
}.not_to perform_at_least(10_000).ips
|
37
|
-
end
|
38
|
-
|
39
|
-
it "fails if the block performs more than 10K ips" do
|
40
|
-
expect {
|
41
|
-
expect { 'x' * 1024 }.not_to perform_at_least(10_000).ips
|
42
|
-
}.to raise_error(/expected block not to perform at least 10000 i\/s, but performed \d+ \(± \d+%\) i\/s/)
|
43
|
-
end
|
44
|
-
end
|
45
|
-
end
|
@@ -1,46 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
RSpec.describe 'RSpec::Benchmark::ComplexityMatcher', '#perform_constant' 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_constant
|
12
|
-
}.to raise_error(StandardError, /boom/)
|
13
|
-
end
|
14
|
-
|
15
|
-
context "expect { ... }.to perfom_constant" do
|
16
|
-
it "passes if the block performs constant" do
|
17
|
-
expect { |n, i|
|
18
|
-
n * i
|
19
|
-
}.to perform_constant.in_range(1, 1000).sample(100)
|
20
|
-
end
|
21
|
-
|
22
|
-
it "fails if the block doesn't perform constant" do
|
23
|
-
expect {
|
24
|
-
expect { |n, i|
|
25
|
-
fibonacci(n)
|
26
|
-
}.to perform_constant.in_range(1, 15).ratio(2).sample(100)
|
27
|
-
}.to raise_error("expected block to perform constant, but performed exponential")
|
28
|
-
end
|
29
|
-
end
|
30
|
-
|
31
|
-
context "expect { ... }.not_to perfom_constant" do
|
32
|
-
it "passes if the block does not perform constant" do
|
33
|
-
expect { |n, i|
|
34
|
-
fibonacci(n)
|
35
|
-
}.not_to perform_constant.in_range(1, 15).ratio(2).sample(100)
|
36
|
-
end
|
37
|
-
|
38
|
-
it "fails if the block doesn't perform constant" do
|
39
|
-
expect {
|
40
|
-
expect { |n, i|
|
41
|
-
n * i
|
42
|
-
}.not_to perform_constant.in_range(1, 1000).sample(100)
|
43
|
-
}.to raise_error("expected block not to perform constant, but performed constant")
|
44
|
-
end
|
45
|
-
end
|
46
|
-
end
|
@@ -1,42 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
RSpec.describe 'RSpec::Benchmark::ComplexityMatcher', '#perform_exponential' 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_exponential
|
12
|
-
}.to raise_error(StandardError, /boom/)
|
13
|
-
end
|
14
|
-
|
15
|
-
context "expect { ... }.to perfom_exponential" do
|
16
|
-
it "passes if the block performs exponential" do
|
17
|
-
expect { |n, i|
|
18
|
-
fibonacci(n)
|
19
|
-
}.to perform_exp.in_range(1, 15).ratio(2).sample(100)
|
20
|
-
end
|
21
|
-
|
22
|
-
it "fails if the block doesn't perform exponential" do
|
23
|
-
expect {
|
24
|
-
expect { |n| n }.to perform_exponential.in_range(1, 10_000).sample(100)
|
25
|
-
}.to raise_error("expected block to perform exponential, but performed constant")
|
26
|
-
end
|
27
|
-
end
|
28
|
-
|
29
|
-
context "expect { ... }.not_to perfom_exponential" do
|
30
|
-
it "passes if the block does not perform exponential" do
|
31
|
-
expect { |n| n }.not_to perform_exponential.in_range(1, 10_000).sample(100)
|
32
|
-
end
|
33
|
-
|
34
|
-
it "fails if the block doesn't perform exponential" do
|
35
|
-
expect {
|
36
|
-
expect { |n|
|
37
|
-
fibonacci(n)
|
38
|
-
}.not_to perform_exponential.in_range(1, 15).ratio(2).sample(100)
|
39
|
-
}.to raise_error("expected block not to perform exponential, but performed exponential")
|
40
|
-
end
|
41
|
-
end
|
42
|
-
end
|
@@ -1,80 +0,0 @@
|
|
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
|
-
trend = [:linear, {linear: {residual: 0.95}}]
|
18
|
-
allow(::Benchmark::Trend).to receive(:range).and_return(range)
|
19
|
-
allow(::Benchmark::Trend).to receive(:infer_trend).and_return(trend)
|
20
|
-
|
21
|
-
expect { |n, i| n }.to perform_linear
|
22
|
-
|
23
|
-
expect(::Benchmark::Trend).to have_received(:range).with(8, 8192, ratio: 8)
|
24
|
-
end
|
25
|
-
|
26
|
-
it "changes default range using in_range and ratio matchers" do
|
27
|
-
range = [1,2,3]
|
28
|
-
trend = [:linear, {linear: {residual: 0.95}}]
|
29
|
-
allow(::Benchmark::Trend).to receive(:range).and_return(range)
|
30
|
-
allow(::Benchmark::Trend).to receive(:infer_trend).and_return(trend)
|
31
|
-
|
32
|
-
expect { |n, i| n }.to perform_linear.in_range(3, 33_000).ratio(2)
|
33
|
-
|
34
|
-
expect(::Benchmark::Trend).to have_received(:range).with(3, 33_000, ratio: 2)
|
35
|
-
end
|
36
|
-
|
37
|
-
it "fails when wrong argument for range" do
|
38
|
-
expect {
|
39
|
-
expect { |n, i| }.to perform_linear.in_range(1..10)
|
40
|
-
}.to raise_error(ArgumentError, "Wrong range argument '1..10', it expects an array or numeric start value.")
|
41
|
-
end
|
42
|
-
|
43
|
-
context "expect { ... }.to perfom_linear" do
|
44
|
-
it "passes if the block performs linear" do
|
45
|
-
range = bench_range(1, 8 << 10)
|
46
|
-
numbers = range.map { |n| Array.new(n) { rand(n) } }
|
47
|
-
|
48
|
-
expect { |n, i|
|
49
|
-
numbers[i].max
|
50
|
-
}.to perform_linear.in_range(range).sample(100).threshold(0.85)
|
51
|
-
end
|
52
|
-
|
53
|
-
it "fails if the block doesn't perform linear" do
|
54
|
-
expect {
|
55
|
-
expect { |n, i|
|
56
|
-
fibonacci(n)
|
57
|
-
}.to perform_linear.in_range(1, 18).ratio(2).sample(100)
|
58
|
-
}.to raise_error("expected block to perform linear, but performed exponential")
|
59
|
-
end
|
60
|
-
end
|
61
|
-
|
62
|
-
context "expect { ... }.not_to perfom_linear" do
|
63
|
-
it "passes if the block does not perform linear" do
|
64
|
-
expect { |n, i|
|
65
|
-
fibonacci(n)
|
66
|
-
}.not_to perform_linear.in_range(1, 18).ratio(2).sample(100)
|
67
|
-
end
|
68
|
-
|
69
|
-
it "fails if the block doesn't perform linear" do
|
70
|
-
range = bench_range(10, 8 << 12)
|
71
|
-
numbers = range.map { |n| Array.new(n) { rand(n) } }
|
72
|
-
|
73
|
-
expect {
|
74
|
-
expect { |n, i|
|
75
|
-
numbers[i].max
|
76
|
-
}.not_to perform_linear.in_range(range[0], range[-1]).sample(100)
|
77
|
-
}.to raise_error("expected block not to perform linear, but performed linear")
|
78
|
-
end
|
79
|
-
end
|
80
|
-
end
|