rspeed 0.0.1 → 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (67) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +32 -0
  3. data/LICENSE +1 -1
  4. data/README.md +88 -5
  5. data/lib/generators/rspeed/install_generator.rb +13 -0
  6. data/lib/generators/rspeed/templates/lib/tasks/rspeed.rb +9 -0
  7. data/lib/rspeed.rb +9 -0
  8. data/lib/rspeed/env.rb +43 -0
  9. data/lib/rspeed/extension.rb +12 -0
  10. data/lib/rspeed/observer.rb +43 -0
  11. data/lib/rspeed/redis.rb +55 -0
  12. data/lib/rspeed/runner.rb +13 -0
  13. data/lib/rspeed/splitter.rb +130 -0
  14. data/lib/rspeed/variable.rb +31 -0
  15. data/lib/rspeed/version.rb +1 -1
  16. data/spec/common_helper.rb +10 -0
  17. data/spec/fixtures/1_spec.rb +9 -0
  18. data/spec/fixtures/2_spec.rb +5 -0
  19. data/spec/fixtures/empty.rb +4 -0
  20. data/spec/fixtures/new_spec.rb.csv +1 -0
  21. data/spec/models/rspeed/env/db_spec.rb +17 -0
  22. data/spec/models/rspeed/env/host_spec.rb +17 -0
  23. data/spec/models/rspeed/env/name_spec.rb +17 -0
  24. data/spec/models/rspeed/env/pipe_spec.rb +19 -0
  25. data/spec/models/rspeed/env/pipes_spec.rb +41 -0
  26. data/spec/models/rspeed/env/port_spec.rb +17 -0
  27. data/spec/models/rspeed/env/result_key_spec.rb +19 -0
  28. data/spec/models/rspeed/env/rspeed_spec.rb +43 -0
  29. data/spec/models/rspeed/env/tmp_spec.rb +19 -0
  30. data/spec/models/rspeed/observer/after_spec.rb +16 -0
  31. data/spec/models/rspeed/observer/after_suite_spec.rb +46 -0
  32. data/spec/models/rspeed/observer/before_spec.rb +15 -0
  33. data/spec/models/rspeed/observer/before_suite_spec.rb +37 -0
  34. data/spec/models/rspeed/redis/clean_pipes_flag_spec.rb +14 -0
  35. data/spec/models/rspeed/redis/client_spec.rb +7 -0
  36. data/spec/models/rspeed/redis/destroy_spec.rb +29 -0
  37. data/spec/models/rspeed/redis/get_spec.rb +9 -0
  38. data/spec/models/rspeed/redis/keys_spec.rb +29 -0
  39. data/spec/models/rspeed/redis/result_spec.rb +13 -0
  40. data/spec/models/rspeed/redis/set_spec.rb +9 -0
  41. data/spec/models/rspeed/redis/specs_finished_spec.rb +19 -0
  42. data/spec/models/rspeed/redis/specs_initiated_spec.rb +13 -0
  43. data/spec/models/rspeed/runner/run_spec.rb +30 -0
  44. data/spec/models/rspeed/splitter/actual_examples_spec.rb +26 -0
  45. data/spec/models/rspeed/splitter/append_spec.rb +35 -0
  46. data/spec/models/rspeed/splitter/diff_spec.rb +30 -0
  47. data/spec/models/rspeed/splitter/first_pipe_spec.rb +17 -0
  48. data/spec/models/rspeed/splitter/get_spec.rb +74 -0
  49. data/spec/models/rspeed/splitter/pipe_files_spec.rb +26 -0
  50. data/spec/models/rspeed/splitter/redundant_run_spec.rb +45 -0
  51. data/spec/models/rspeed/splitter/rename_spec.rb +16 -0
  52. data/spec/models/rspeed/splitter/split_spec.rb +89 -0
  53. data/spec/models/rspeed/variable/append_name_spec.rb +19 -0
  54. data/spec/models/rspeed/variable/csv_spec.rb +5 -0
  55. data/spec/models/rspeed/variable/default_partner_spec.rb +5 -0
  56. data/spec/models/rspeed/variable/key_spec.rb +15 -0
  57. data/spec/models/rspeed/variable/pipe_name_spec.rb +15 -0
  58. data/spec/models/rspeed/variable/pipes_pattern_spec.rb +5 -0
  59. data/spec/models/rspeed/variable/result_spec.rb +19 -0
  60. data/spec/models/rspeed/variable/tmp_spec.rb +15 -0
  61. data/spec/spec_helper.rb +27 -0
  62. data/spec/support/common.rb +5 -3
  63. data/spec/support/coverage.rb +14 -0
  64. data/spec/support/env_mock.rb +3 -0
  65. data/spec/support/fakeredis.rb +3 -0
  66. metadata +180 -23
  67. data/spec/rails_helper.rb +0 -9
@@ -0,0 +1,29 @@
1
+ # frozen_string_literal: true
2
+
3
+ RSpec.describe RSpeed::Redis, '#destroy' do
4
+ let!(:redis) { described_class }
5
+
6
+ before do
7
+ redis.set('rspeed', '{}')
8
+ redis.set('rspeed_1', '{}')
9
+ redis.set('rspeed_2', '{}')
10
+ end
11
+
12
+ it 'destroys via wildcard' do
13
+ redis.destroy('rspeed_*')
14
+
15
+ expect(redis.keys('*')).to eq %w[rspeed]
16
+ end
17
+
18
+ it 'destroys via single name' do
19
+ redis.destroy('rspeed')
20
+
21
+ expect(redis.keys('*')).to eq %w[rspeed_1 rspeed_2]
22
+ end
23
+
24
+ it 'destroys default partner when no pattern is given' do
25
+ redis.destroy
26
+
27
+ expect(redis.keys('*')).to eq %w[rspeed]
28
+ end
29
+ end
@@ -0,0 +1,9 @@
1
+ # frozen_string_literal: true
2
+
3
+ RSpec.describe RSpeed::Redis, '.set' do
4
+ it 'sets a key on redis' do
5
+ described_class.client.set('key', 'value')
6
+
7
+ expect(described_class.get('key')).to eq('value')
8
+ end
9
+ end
@@ -0,0 +1,29 @@
1
+ # frozen_string_literal: true
2
+
3
+ RSpec.describe RSpeed::Redis, '.keys' do
4
+ subject(:redis) { described_class }
5
+
6
+ context 'with default config' do
7
+ before do
8
+ described_class.set('rspeed_1', 'value_1')
9
+ described_class.set('rspeed_2', 'value_2')
10
+ described_class.set('rspeed_3', 'value_3')
11
+ end
12
+
13
+ it 'shows keys' do
14
+ expect(redis.keys).to eq %w[rspeed_1 rspeed_2 rspeed_3]
15
+ end
16
+ end
17
+
18
+ context 'with custom key' do
19
+ before do
20
+ described_class.set('custom_key_1', 'value_1')
21
+ described_class.set('custom_key_2', 'value_2')
22
+ described_class.set('custom_key_3', 'value_3')
23
+ end
24
+
25
+ it 'shows keys' do
26
+ expect(redis.keys('custom_key_*')).to eq %w[custom_key_1 custom_key_2 custom_key_3]
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ RSpec.describe RSpeed::Redis, '#result?' do
4
+ context 'when has no key rspeed on redis' do
5
+ it { expect(described_class.result?).to be(false) }
6
+ end
7
+
8
+ context 'when has key rspeed on redis' do
9
+ before { described_class.set('rspeed', { files: [[1, '1_spec.rb']], number: 0, total: 1 }.to_json) }
10
+
11
+ it { expect(described_class.result?).to be(true) }
12
+ end
13
+ end
@@ -0,0 +1,9 @@
1
+ # frozen_string_literal: true
2
+
3
+ RSpec.describe RSpeed::Redis, '.set' do
4
+ it 'sets a key on redis' do
5
+ described_class.set('key', 'value')
6
+
7
+ expect(described_class.client.get('key')).to eq('value')
8
+ end
9
+ end
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: true
2
+
3
+ RSpec.describe RSpeed::Redis, '.specs_finished?' do
4
+ before do
5
+ described_class.set('rspeed_pipe_1', '1.0')
6
+
7
+ allow(RSpeed::Env).to receive(:pipes).and_return(2)
8
+ end
9
+
10
+ context 'when the quantity of pipe result is not the same as the quantity of pipes' do
11
+ it { expect(described_class.specs_finished?).to be(false) }
12
+ end
13
+
14
+ context 'when the quantity of pipe result is the same as the quantity of pipes' do
15
+ before { described_class.set('rspeed_pipe_2', '2.0') }
16
+
17
+ it { expect(described_class.specs_finished?).to be(true) }
18
+ end
19
+ end
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ RSpec.describe RSpeed::Redis, '.specs_initiated?' do
4
+ context 'when has no pipe flag key' do
5
+ it { expect(described_class.specs_finished?).to be(false) }
6
+ end
7
+
8
+ context 'when has at least one pipe flag key' do
9
+ before { described_class.set('rspeed_pipe_1', '1.0') }
10
+
11
+ it { expect(described_class.specs_finished?).to be(true) }
12
+ end
13
+ end
@@ -0,0 +1,30 @@
1
+ # frozen_string_literal: true
2
+
3
+ RSpec.describe RSpeed::Runner, '#run' do
4
+ let!(:shell) { double('shell') }
5
+ let!(:splitter) { instance_double('RSpeed::Splitter') }
6
+
7
+ before { allow(RSpeed::Splitter).to receive(:new).and_return(splitter) }
8
+
9
+ context 'when is a redundant run' do
10
+ before { allow(splitter).to receive(:redundant_run?).and_return(true) }
11
+
12
+ it 'aborts the run' do
13
+ expect(described_class.run(shell)).to be(nil)
14
+ end
15
+ end
16
+
17
+ context 'when is not a redundant run' do
18
+ before do
19
+ allow(splitter).to receive(:redundant_run?).and_return(false)
20
+ allow(shell).to receive(:call)
21
+ allow(splitter).to receive(:pipe_files).and_return('spec_1.rb spec_2.rb')
22
+ end
23
+
24
+ it 'run the pipe specs' do
25
+ described_class.run(shell)
26
+
27
+ expect(shell).to have_received(:call).with('bundle exec rspec spec_1.rb spec_2.rb')
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,26 @@
1
+ # frozen_string_literal: true
2
+
3
+ RSpec.describe RSpeed::Splitter, '#actual_examples' do
4
+ it 'returns all examples' do
5
+ splitter = described_class.new(specs_path: 'spec/fixtures/**/*_spec.rb')
6
+
7
+ expect(splitter.actual_examples).to eq [
8
+ 'spec/fixtures/1_spec.rb:4',
9
+ 'spec/fixtures/1_spec.rb:6',
10
+ 'spec/fixtures/1_spec.rb:8',
11
+ 'spec/fixtures/2_spec.rb:4',
12
+ ]
13
+ end
14
+
15
+ it 'does not raise when no file match' do
16
+ splitter = described_class.new(specs_path: 'spec/fixtures/**/*_missing.rb')
17
+
18
+ expect(splitter.actual_examples).to eq []
19
+ end
20
+
21
+ it 'does not raise when file is empty' do
22
+ splitter = described_class.new(specs_path: 'spec/fixtures/**/empty.rb')
23
+
24
+ expect(splitter.actual_examples).to eq []
25
+ end
26
+ end
@@ -0,0 +1,35 @@
1
+ # frozen_string_literal: true
2
+
3
+ RSpec.describe RSpeed::Splitter, '#append' do
4
+ subject(:splitter) { described_class.new }
5
+
6
+ it 'appends file and time on rspeed key' do
7
+ splitter.append [[1, '1_spec.rb'], [2, '2_spec.rb']]
8
+
9
+ expect(splitter.get('rspeed_tmp')).to eq [
10
+ '{"file":"2_spec.rb","time":2.0}',
11
+ '{"file":"1_spec.rb","time":1.0}',
12
+ ]
13
+ end
14
+
15
+ context 'when files is not given' do
16
+ before do
17
+ truncate_file
18
+ populate_csv_file
19
+ end
20
+
21
+ it 'read csv and append file and time on rspeed key' do
22
+ splitter.append
23
+
24
+ expect(splitter.get('rspeed_tmp')).to eq [
25
+ '{"file":"./spec/0_2_spec.rb","time":0.2}',
26
+ '{"file":"./spec/0_3_spec.rb","time":0.3}',
27
+ '{"file":"./spec/0_4_spec.rb","time":0.4}',
28
+ '{"file":"./spec/0_7_spec.rb","time":0.7}',
29
+ '{"file":"./spec/1_1_spec.rb","time":1.1}',
30
+ '{"file":"./spec/1_5_spec.rb","time":1.5}',
31
+ '{"file":"./spec/2_0_spec.rb","time":2.0}',
32
+ ]
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,30 @@
1
+ # frozen_string_literal: true
2
+
3
+ RSpec.describe RSpeed::Splitter, '#diff' do
4
+ subject(:splitter) { described_class.new(specs_path: './spec/fixtures/*_spec.rb') }
5
+
6
+ let!(:redis) { redis_object }
7
+
8
+ before do
9
+ redis.lpush 'rspeed', { file: './spec/fixtures/1_spec.rb:4', time: '1.4' }.to_json
10
+ redis.lpush 'rspeed', { file: './spec/fixtures/1_spec.rb:6', time: '1.6' }.to_json
11
+ redis.lpush 'rspeed', { file: './spec/fixtures/1_spec.rb:8', time: '1.8' }.to_json
12
+ redis.lpush 'rspeed', { file: './spec/fixtures/2_spec.rb:4', time: '2.4' }.to_json
13
+ redis.lpush 'rspeed', { file: './spec/fixtures/2_spec.rb:666', time: '6' }.to_json
14
+ redis.lpush 'rspeed', { file: './spec/fixtures/x_spec.rb:1', time: 3 }.to_json
15
+
16
+ File.open('spec/fixtures/new_spec.rb', 'a') { |file| file.write('it') }
17
+ end
18
+
19
+ after { delete_file('spec/fixtures/new_spec.rb') }
20
+
21
+ it 'removes removed specs and adds new spec and keeps keeped specs based on rspeed key values' do
22
+ expect(splitter.diff).to eq [
23
+ { file: './spec/fixtures/2_spec.rb:4', time: '2.4' },
24
+ { file: './spec/fixtures/1_spec.rb:8', time: '1.8' },
25
+ { file: './spec/fixtures/1_spec.rb:6', time: '1.6' },
26
+ { file: './spec/fixtures/1_spec.rb:4', time: '1.4' },
27
+ { file: './spec/fixtures/new_spec.rb:1', time: 0 },
28
+ ]
29
+ end
30
+ end
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ RSpec.describe RSpeed::Splitter, '.first_pipe?' do
4
+ subject(:splitter) { described_class.new }
5
+
6
+ context 'when pipe env is 1' do
7
+ before { allow(RSpeed::Env).to receive(:pipe).and_return 1 }
8
+
9
+ it { expect(splitter.first_pipe?).to eq true }
10
+ end
11
+
12
+ context 'when pipe env is not 1' do
13
+ before { allow(RSpeed::Env).to receive(:pipe).and_return 2 }
14
+
15
+ it { expect(splitter.first_pipe?).to eq false }
16
+ end
17
+ end
@@ -0,0 +1,74 @@
1
+ # frozen_string_literal: true
2
+
3
+ RSpec.describe RSpeed::Splitter, '#get' do
4
+ subject(:splitter) { described_class.new }
5
+
6
+ let!(:redis) { redis_object }
7
+
8
+ context 'when wildcard pattern is given' do
9
+ before do
10
+ redis.set 'rspeed_1', { files: [[1, '1_spec.rb'], [2, '2_spec.rb']], number: 0, total: 3 }.to_json
11
+ redis.set 'rspeed_2', { files: [[3, '3_spec.rb']], number: 1, total: 3 }.to_json
12
+ end
13
+
14
+ it 'returns all values' do
15
+ expect(splitter.get('rspeed_*')).to eq [
16
+ {
17
+ 'files' => [[1, '1_spec.rb'], [2, '2_spec.rb']],
18
+ 'number' => 0,
19
+ 'total' => 3,
20
+ },
21
+
22
+ {
23
+ 'files' => [[3, '3_spec.rb']],
24
+ 'number' => 1,
25
+ 'total' => 3,
26
+ },
27
+ ]
28
+ end
29
+ end
30
+
31
+ context 'when normal pattern is given' do
32
+ before do
33
+ redis.set 'pattern', { files: [[1, '1_spec.rb'], [2, '2_spec.rb']], number: 0, total: 3 }.to_json
34
+ end
35
+
36
+ it 'returns all values from that key' do
37
+ expect(splitter.get('pattern')).to eq [
38
+ {
39
+ 'files' => [[1, '1_spec.rb'], [2, '2_spec.rb']],
40
+ 'number' => 0,
41
+ 'total' => 3,
42
+ },
43
+ ]
44
+ end
45
+ end
46
+
47
+ context 'when pattern is rspeed' do
48
+ before do
49
+ redis.lpush 'rspeed', { file: '1_spec.rb', time: 1 }.to_json
50
+ redis.lpush 'rspeed', { file: '2_spec.rb', time: 2 }.to_json
51
+ end
52
+
53
+ it 'executes the right fetch method' do
54
+ expect(splitter.get('rspeed')).to eq [
55
+ '{"file":"2_spec.rb","time":2}',
56
+ '{"file":"1_spec.rb","time":1}',
57
+ ]
58
+ end
59
+ end
60
+
61
+ context 'when pattern is rspeed_tmp' do
62
+ before do
63
+ redis.lpush 'rspeed_tmp', { file: '1_spec.rb', time: 1 }.to_json
64
+ redis.lpush 'rspeed_tmp', { file: '2_spec.rb', time: 2 }.to_json
65
+ end
66
+
67
+ it 'executes the right fetch method' do
68
+ expect(splitter.get('rspeed_tmp')).to eq [
69
+ '{"file":"2_spec.rb","time":2}',
70
+ '{"file":"1_spec.rb","time":1}',
71
+ ]
72
+ end
73
+ end
74
+ end
@@ -0,0 +1,26 @@
1
+ # frozen_string_literal: true
2
+
3
+ RSpec.describe RSpeed::Splitter, '#pipe_files' do
4
+ let!(:shell) { double('shell') }
5
+ let!(:splitter) { described_class.new }
6
+
7
+ before { allow(RSpeed::Env).to receive(:pipe).and_return(1) }
8
+
9
+ context 'when has no result' do
10
+ before { allow(RSpeed::Redis).to receive(:result?).and_return(false) }
11
+
12
+ it { expect(splitter.pipe_files).to be(nil) }
13
+ end
14
+
15
+ context 'when has result' do
16
+ before do
17
+ allow(RSpeed::Redis).to receive(:result?).and_return(true)
18
+
19
+ allow(splitter).to receive(:split).and_return(rspeed_1: { files: [{ file: 'spec_1.rb' }, { file: 'spec_2.rb' }] })
20
+ end
21
+
22
+ it 'returns the splitted pipe files' do
23
+ expect(splitter.pipe_files).to eq 'spec_1.rb spec_2.rb'
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,45 @@
1
+ # frozen_string_literal: true
2
+
3
+ RSpec.describe RSpeed::Splitter, '.redundant_run?' do
4
+ subject(:splitter) { described_class.new }
5
+
6
+ context 'when is not pipe 1' do
7
+ before { allow(RSpeed::Env).to receive(:pipe).and_return(2) }
8
+
9
+ context 'when result key exists' do
10
+ let!(:redis) { redis_object }
11
+
12
+ before do
13
+ redis.set('rspeed', '{}')
14
+
15
+ allow(RSpeed::Env).to receive(:pipe).and_return(2)
16
+ end
17
+
18
+ it { expect(splitter.redundant_run?).to be(false) }
19
+ end
20
+
21
+ context 'when result key does not exist' do
22
+ it { expect(splitter.redundant_run?).to be(true) }
23
+ end
24
+ end
25
+
26
+ context 'when is the first pipe' do
27
+ before { allow(RSpeed::Env).to receive(:pipe).and_return(1) }
28
+
29
+ context 'when result key exists' do
30
+ let!(:redis) { redis_object }
31
+
32
+ before do
33
+ redis.set('rspeed', '{}')
34
+
35
+ allow(RSpeed::Env).to receive(:pipe).and_return(2)
36
+ end
37
+
38
+ it { expect(splitter.redundant_run?).to be(false) }
39
+ end
40
+
41
+ context 'when result key does not exist' do
42
+ it { expect(splitter.redundant_run?).to be(false) }
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,16 @@
1
+ # frozen_string_literal: true
2
+
3
+ RSpec.describe RSpeed::Splitter, '#rename' do
4
+ subject(:splitter) { described_class.new }
5
+
6
+ let!(:redis) { redis_object }
7
+
8
+ before { redis.lpush('rspeed_tmp', { file: '1_spec.rb', time: 1.0 }.to_json) }
9
+
10
+ it 'renames the key' do
11
+ splitter.rename
12
+
13
+ expect(redis.lrange('rspeed_tmp', 0, -1)).to eq([])
14
+ expect(redis.lrange('rspeed', 0, -1)).to eq(['{"file":"1_spec.rb","time":1.0}'])
15
+ end
16
+ end
@@ -0,0 +1,89 @@
1
+ # frozen_string_literal: true
2
+
3
+ RSpec.describe RSpeed::Splitter, '.split' do
4
+ subject(:splitter) { described_class.new }
5
+
6
+ let!(:unsorted_data) do
7
+ [
8
+ { file: './spec/1_5_spec.rb', time: '1.5' },
9
+ { file: './spec/1_1_spec.rb', time: '1.1' },
10
+ { file: './spec/0_7_spec.rb', time: '0.7' },
11
+ { file: './spec/0_4_spec.rb', time: '0.4' },
12
+ { file: './spec/0_3_spec.rb', time: '0.3' },
13
+ { file: './spec/0_2_spec.rb', time: '0.2' },
14
+ { file: './spec/2_0_spec.rb', time: '2.0' },
15
+ ]
16
+ end
17
+
18
+ before { allow(RSpeed::Env).to receive(:pipes).and_return 3 }
19
+
20
+ context 'when diff is given' do
21
+ it 'splits the times between the pipes' do
22
+ expect(splitter.split(unsorted_data)).to eq(
23
+ rspeed_1: {
24
+ files: [{ file: './spec/2_0_spec.rb', time: 2.0 }],
25
+ number: 1,
26
+ total: 2.0,
27
+ },
28
+
29
+ rspeed_2: {
30
+ files: [
31
+ { file: './spec/1_5_spec.rb', time: 1.5 },
32
+ { file: './spec/0_4_spec.rb', time: 0.4 },
33
+ { file: './spec/0_2_spec.rb', time: 0.2 },
34
+ ],
35
+
36
+ number: 2,
37
+ total: 1.5 + 0.4 + 0.2, # 1.5 -> 1.9 -> 2.1
38
+ },
39
+
40
+ rspeed_3: {
41
+ files: [
42
+ { file: './spec/1_1_spec.rb', time: 1.1 },
43
+ { file: './spec/0_7_spec.rb', time: 0.7 },
44
+ { file: './spec/0_3_spec.rb', time: 0.3 },
45
+ ],
46
+
47
+ number: 3,
48
+ total: 1.1 + 0.7 + 0.3, # 1.1 -> 1.8 -> 2.1
49
+ }
50
+ )
51
+ end
52
+ end
53
+
54
+ context 'when diff is not given' do
55
+ before { allow(splitter).to receive(:diff).and_return(unsorted_data) }
56
+
57
+ it 'splits the diff result into times between the pipes' do
58
+ expect(splitter.split).to eq(
59
+ rspeed_1: {
60
+ files: [{ file: './spec/2_0_spec.rb', time: 2.0 }],
61
+ number: 1,
62
+ total: 2.0,
63
+ },
64
+
65
+ rspeed_2: {
66
+ files: [
67
+ { file: './spec/1_5_spec.rb', time: 1.5 },
68
+ { file: './spec/0_4_spec.rb', time: 0.4 },
69
+ { file: './spec/0_2_spec.rb', time: 0.2 },
70
+ ],
71
+
72
+ number: 2,
73
+ total: 1.5 + 0.4 + 0.2, # 1.5 -> 1.9 -> 2.1
74
+ },
75
+
76
+ rspeed_3: {
77
+ files: [
78
+ { file: './spec/1_1_spec.rb', time: 1.1 },
79
+ { file: './spec/0_7_spec.rb', time: 0.7 },
80
+ { file: './spec/0_3_spec.rb', time: 0.3 },
81
+ ],
82
+
83
+ number: 3,
84
+ total: 1.1 + 0.7 + 0.3, # 1.1 -> 1.8 -> 2.1
85
+ }
86
+ )
87
+ end
88
+ end
89
+ end