rspec-benchmark 0.5.1 → 0.6.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|