spec_tiller 0.0.7 → 1.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -13
- data/.gitignore +17 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +89 -0
- data/Rakefile +1 -0
- data/lib/spec_tiller/build_matrix_parser.rb +30 -0
- data/lib/spec_tiller/distribute_spec_files.rb +125 -0
- data/lib/spec_tiller/sync_spec_file_list.rb +93 -0
- data/lib/spec_tiller/version.rb +3 -0
- data/lib/spec_tiller.rb +4 -0
- data/spec/build_matrix_parser_spec.rb +62 -0
- data/spec/distribute_spec_files_spec.rb +162 -0
- data/spec/documents/.travis.yml +34 -0
- data/spec/documents/rspec_profile_results.txt +23 -0
- data/spec/spec_helper.rb +8 -0
- data/spec/sync_spec_file_list_spec.rb +48 -0
- data/spec_tiller.gemspec +28 -0
- metadata +54 -14
checksums.yaml
CHANGED
@@ -1,15 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
|
5
|
-
data.tar.gz: !binary |-
|
6
|
-
YjhkMmVkNzg0N2M3YzZjMTNhMGMxNTAxMmZlNDgzOGZjZDZiMDlhYQ==
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: e9b13142ceda1474ca093cd92a29fb161ea83642
|
4
|
+
data.tar.gz: 45db628b9fff9bc1c00457343564c995b4599fbd
|
7
5
|
SHA512:
|
8
|
-
metadata.gz:
|
9
|
-
|
10
|
-
ZTgxMzBkNTVjYjlkMmU2YTJkMWEzM2FhNmFhZmVlMmJlOTE3NDdmNmY0NmQw
|
11
|
-
ZDNlOTgwYTJmOWVhM2RmYjllNWU3ZTBiMjU5OTUzOGQ4YTc3MzY=
|
12
|
-
data.tar.gz: !binary |-
|
13
|
-
MjBhMjA0ZTcyOTU4MGIzODhlYWVkMDVlMDY0ZTI5NmYzYjZhMjc2YTNjOTk1
|
14
|
-
OTUxYzYzMjc5NmZmY2I1ODQ2NjRiOWVhOWRiNmVkODc3MjQzNmZmMDY4NzE2
|
15
|
-
N2VjNmY1ZjVkODZhZWEzOGQxZjY0MmZlZDk4NTRjNDI1NzczYmY=
|
6
|
+
metadata.gz: c8fecb888fa57185e06e798c688d6f897ebbfc4339b9fb9f57a1e43f84c41bf5859a8f76f74a807841d69c85c6a8f154fa89fe504f449df752ca5a532b533655
|
7
|
+
data.tar.gz: 0101f1acd5dc9af7ffdb0c2e033310ed942dfde104fd89965cbc55a32b819b13c96c998a2fe2174f109c864fcf8543ae6a8d8d86825dbfd50d50d47704e3b88a
|
data/.gitignore
ADDED
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2014 Matt Schmaus - Greenhouse
|
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.
|
data/README.md
ADDED
@@ -0,0 +1,89 @@
|
|
1
|
+
# SpecTiller
|
2
|
+
|
3
|
+
## Description
|
4
|
+
This gem will parse the output of calling "rspec --perform", and then will redistribute the spec files evenly, based on file run time, across all builds established in the travis.yml file in order to optimize your test suite's run time. As of now, this gem is only compatible with Travis CI and their build matrix setup. For more information on this setup, check [here](http://docs.travis-ci.com/user/build-configuration/#The-Build-Matrix).
|
5
|
+
|
6
|
+
## Installation
|
7
|
+
|
8
|
+
Add this line to your application's ``Gemfile`` in **both** *development* and *test* groups:
|
9
|
+
|
10
|
+
group :development, :test do
|
11
|
+
gem 'spec_tiller'
|
12
|
+
end
|
13
|
+
|
14
|
+
And then execute:
|
15
|
+
|
16
|
+
$ bundle
|
17
|
+
|
18
|
+
## Set Up
|
19
|
+
|
20
|
+
#### Git Hooks
|
21
|
+
In order to make sure that the travis file remains up to date with any newly added or removed spec files, you'll have to include a rake task in your pre-commit and post-merge git hooks. Create two files in .git/hooks/ --> ``pre-commit`` and ``post-merge`` (no file extension). **Please make sure that these files are executable** (more information on [git hooks](http://git-scm.com/book/en/Customizing-Git-Git-Hooks)). In each of those two files, add the following rake task:
|
22
|
+
|
23
|
+
#!/bin/sh
|
24
|
+
rake spec_tiller:sync
|
25
|
+
|
26
|
+
Upon setting this up, any time you commit or merge, you'll notice the following output:
|
27
|
+
|
28
|
+
Syncing list of spec files...
|
29
|
+
Removed: [spec/file/removed_spec.rb]
|
30
|
+
Added: [spec/file/added_spec.rb, spec/file/another_added_spec.rb]
|
31
|
+
|
32
|
+
####.travis.yml
|
33
|
+
In your ``.travis.yml`` file, create a top-level variable **num_builds** and set it to the number of builds you want the spec files distributed over (deafult value is 5 builds). You must also make sure that the base of your script is as follows:
|
34
|
+
|
35
|
+
bundle exec rspec $TEST_SUITE
|
36
|
+
|
37
|
+
*$TEST_SUITE* represents an environment variable. For the purpose of this gem, a list of space-separated spec files will be assigned to that variable. So, lets say that in ``.travis.yml``, *TEST_SUITE="spec/path/file_one_spec.rb spec/path/file_two_spec.rb spec/path/file_three_spec.rb"*, then the script above will execute as follows:
|
38
|
+
|
39
|
+
bundle exec rspec spec/path/file_one_spec.rb spec/path/file_two_spec.rb spec/path/file_three_spec.rb
|
40
|
+
|
41
|
+
Here is an example of what a ``.travis.yml`` file may look like after all is said and done.:
|
42
|
+
|
43
|
+
language: ruby
|
44
|
+
rvm:
|
45
|
+
- 1.9.3
|
46
|
+
branches:
|
47
|
+
only:
|
48
|
+
- develop
|
49
|
+
- master
|
50
|
+
- /^release\/.*$/
|
51
|
+
- /^hotfix\/.*$/
|
52
|
+
- /^feature\/testing-.+$/
|
53
|
+
cache: bundler
|
54
|
+
before_install:
|
55
|
+
- export DISPLAY=:99.0
|
56
|
+
- sh -e /etc/init.d/xvfb start
|
57
|
+
before_script:
|
58
|
+
- psql -c 'create database test;' -U postgres
|
59
|
+
- RAILS_ENV=test bundle exec rake --trace db:test:load db:seed
|
60
|
+
script:
|
61
|
+
- bundle exec rspec $TEST_SUITE --tag ~local_only
|
62
|
+
env:
|
63
|
+
global:
|
64
|
+
- SOME_OTHER_ENV_VAR="hello world"
|
65
|
+
matrix:
|
66
|
+
- TEST_SUITE="spec/path/file_one_spec.rb spec/path/file_two_spec.rb spec/path/file_three_spec.rb"
|
67
|
+
- TEST_SUITE="spec/path/file_four_spec.rb"
|
68
|
+
- TEST_SUITE="spec/path/file_five_spec.rb spec/path/file_six_spec.rb"
|
69
|
+
- TEST_SUITE="spec/path/file_seven_spec.rb spec/path/file_eight_spec.rb spec/path/file_nine_spec.rb spec/path/file_ten_spec.rb"
|
70
|
+
- TEST_SUITE="spec/path/file_eleven_spec.rb spec/path/file_twelve_spec.rb"
|
71
|
+
num_builds: 5
|
72
|
+
|
73
|
+
#### Redistributing Files
|
74
|
+
Initially, and every so often, you will have to redistribute the spec files (make sure everything is properly set up before running this rake task). The *spec_tiller:sync* rake task adds any new spec files to the last bucket, so after a little while, the timing of the build may not be optimal. In order to redistribute the spec files in order to optimize test suite run time, run the following rake task:
|
75
|
+
|
76
|
+
spec_tiller:redistribute
|
77
|
+
|
78
|
+
This will run your whole test suite, keeping track of how long each spec file takes to run, and the will distribute the spec files in order to maximize your test suite's run time, over the number of builds you've designated (with a default value of 5). **This rake task will not print the output of the rake task until it is complete.**
|
79
|
+
***
|
80
|
+
## Feature Requests & Bugs
|
81
|
+
See [http://github.com/grnhse/spec-tiller/issues](http://github.com/grnhse/spec-tiller/issues)
|
82
|
+
|
83
|
+
## Contributing
|
84
|
+
|
85
|
+
1. Fork it
|
86
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
87
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
88
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
89
|
+
5. Create new Pull Request
|
data/Rakefile
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require "bundler/gem_tasks"
|
@@ -0,0 +1,30 @@
|
|
1
|
+
# Includes functions to parse build matrix strings into hashes and to compress them back into strings.'
|
2
|
+
module BuildMatrixParser
|
3
|
+
def parse_env_matrix(content)
|
4
|
+
content['env']['matrix'].map do |matrix_line|
|
5
|
+
if matrix_line.nil?
|
6
|
+
{}
|
7
|
+
else
|
8
|
+
# Input: TEST_SUITE="spec/a.rb spec/b.rb" RUN_JS="true"
|
9
|
+
# Output: { 'TEST_SUITE' => 'spec/a.rb spec/b.rb', 'RUN_JS' => 'true' }
|
10
|
+
Hash[matrix_line.scan(/\s*([^=]+)="\s*([^"]+)"/)]
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
module_function :parse_env_matrix
|
15
|
+
|
16
|
+
def format_matrix(env_matrix)
|
17
|
+
content_env_matrix = []
|
18
|
+
|
19
|
+
env_matrix.each do |var_hash|
|
20
|
+
next if var_hash.empty? || var_hash["TEST_SUITE"].empty?
|
21
|
+
line = var_hash.map { |key, value| %Q(#{key}="#{value}") }.join(' ')
|
22
|
+
|
23
|
+
content_env_matrix << line
|
24
|
+
end
|
25
|
+
|
26
|
+
content_env_matrix
|
27
|
+
end
|
28
|
+
module_function :format_matrix
|
29
|
+
|
30
|
+
end
|
@@ -0,0 +1,125 @@
|
|
1
|
+
require 'rake'
|
2
|
+
require 'yaml'
|
3
|
+
|
4
|
+
namespace :spec_tiller do
|
5
|
+
desc 'Runs whole test suite and redistributes spec files across builds according to file run time'
|
6
|
+
task :redistribute => :environment do
|
7
|
+
travis_yml_file = YAML::load(File.open('.travis.yml'))
|
8
|
+
env_variables = travis_yml_file['env']['global']
|
9
|
+
script = travis_yml_file['script'].first.gsub('$TEST_SUITE ', '')
|
10
|
+
|
11
|
+
profile_results = `#{env_variables.join(' ')} #{script} --profile 1000000000`
|
12
|
+
|
13
|
+
`echo "#{profile_results}" > spec/log/rspec_profile_output.txt`
|
14
|
+
TravisBuildMatrix::SpecDistributor.new(travis_yml_file, profile_results) do |content|
|
15
|
+
File.open('.travis.yml', 'w') { |file| file.write(content.to_yaml(:line_width => -1)) }
|
16
|
+
end
|
17
|
+
puts profile_results
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
module TravisBuildMatrix
|
22
|
+
|
23
|
+
DEFAULT_NUM_BUILDS = 5
|
24
|
+
|
25
|
+
class SpecFile
|
26
|
+
attr_accessor :file_path, :test_duration
|
27
|
+
|
28
|
+
def initialize(file_path, test_duration)
|
29
|
+
@test_duration = test_duration
|
30
|
+
@file_path = file_path
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
class TestBucket
|
35
|
+
attr_reader :spec_files, :total_duration
|
36
|
+
|
37
|
+
def initialize
|
38
|
+
@total_duration = 0.0
|
39
|
+
@spec_files = []
|
40
|
+
end
|
41
|
+
|
42
|
+
def add_to_list(spec_file)
|
43
|
+
@spec_files << spec_file
|
44
|
+
@total_duration += spec_file.test_duration
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
class SpecDistributor
|
49
|
+
|
50
|
+
EXTRACT_DURATION_AND_FILE_PATH = /\s{1}\(([0-9\.]*\s).*\.\/(spec.*):/
|
51
|
+
|
52
|
+
def initialize(travis_yml_file, profile_results, &block)
|
53
|
+
num_buckets = travis_yml_file['num_builds'] || DEFAULT_NUM_BUILDS
|
54
|
+
|
55
|
+
@spec_files = parse_profile_results(profile_results)
|
56
|
+
@test_buckets = Array.new(num_buckets){ |_| TestBucket.new }
|
57
|
+
|
58
|
+
distribute_tests
|
59
|
+
|
60
|
+
TravisBuildMatrix::TravisFile.new(@test_buckets, travis_yml_file, &block)
|
61
|
+
end
|
62
|
+
|
63
|
+
private
|
64
|
+
|
65
|
+
def parse_profile_results(profile_results)
|
66
|
+
|
67
|
+
#Input: Walnuts
|
68
|
+
# 9.96 seconds average (69.69 seconds / 7 examples) ./spec/features/walnut_spec.rb:3
|
69
|
+
#Output: ["9.96", "spec/features/walnut_spec.rb"]
|
70
|
+
extracted_info = profile_results.scan(EXTRACT_DURATION_AND_FILE_PATH).uniq { |spec_file| spec_file.last }
|
71
|
+
|
72
|
+
tests = extracted_info.map do |capture_groups|
|
73
|
+
test_duration = capture_groups.first.strip.to_f
|
74
|
+
test_file_path = capture_groups.last
|
75
|
+
|
76
|
+
SpecFile.new(test_file_path, test_duration)
|
77
|
+
end
|
78
|
+
|
79
|
+
tests.sort_by(&:test_duration).reverse
|
80
|
+
end
|
81
|
+
|
82
|
+
def smallest_bucket
|
83
|
+
@test_buckets.min_by(&:total_duration)
|
84
|
+
end
|
85
|
+
|
86
|
+
def distribute_tests
|
87
|
+
@spec_files.each { |test| smallest_bucket.add_to_list(test) }
|
88
|
+
end
|
89
|
+
|
90
|
+
end
|
91
|
+
|
92
|
+
class TravisFile
|
93
|
+
include BuildMatrixParser
|
94
|
+
|
95
|
+
def initialize(test_buckets, travis_yml_file, &block)
|
96
|
+
rewrite_content(test_buckets, travis_yml_file)
|
97
|
+
block.call(travis_yml_file) if block
|
98
|
+
end
|
99
|
+
|
100
|
+
private
|
101
|
+
|
102
|
+
def rewrite_content(test_buckets, content)
|
103
|
+
content['env']['matrix'] ||= [] # initialize env if not already set
|
104
|
+
|
105
|
+
env_matrix = BuildMatrixParser.parse_env_matrix(content)
|
106
|
+
|
107
|
+
if env_matrix.length > test_buckets.length
|
108
|
+
env_matrix = env_matrix.slice(0, test_buckets.length)
|
109
|
+
elsif env_matrix.length < test_buckets.length
|
110
|
+
(test_buckets.length - env_matrix.length).times {env_matrix.push({ })}
|
111
|
+
end
|
112
|
+
|
113
|
+
env_matrix.each do |var_hash|
|
114
|
+
test_bucket = test_buckets.shift
|
115
|
+
|
116
|
+
spec_file_list = test_bucket.spec_files.map(&:file_path).join(' ')
|
117
|
+
var_hash['TEST_SUITE'] = "#{spec_file_list}"
|
118
|
+
end
|
119
|
+
|
120
|
+
content['env']['matrix'] = BuildMatrixParser.format_matrix(env_matrix)
|
121
|
+
end
|
122
|
+
|
123
|
+
end
|
124
|
+
|
125
|
+
end
|
@@ -0,0 +1,93 @@
|
|
1
|
+
require 'rake'
|
2
|
+
require 'yaml'
|
3
|
+
|
4
|
+
namespace :spec_tiller do
|
5
|
+
desc 'Compares spec files in travis.yml to current list of spec files, and syncs accordingly'
|
6
|
+
task :sync do
|
7
|
+
content = YAML::load(File.open('.travis.yml'))
|
8
|
+
current_file_list = Dir.glob('spec/**/*_spec.rb').map { |file_path| file_path.slice(/(spec\/\S+$)/) }
|
9
|
+
|
10
|
+
puts "\nSyncing list of spec files..."
|
11
|
+
|
12
|
+
SyncSpecFiles.rewrite_travis_content(content, current_file_list) do |original|
|
13
|
+
write_to_file(content)
|
14
|
+
puts file_diff(original, current_file_list)
|
15
|
+
end
|
16
|
+
|
17
|
+
`git add .travis.yml`
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
module SyncSpecFiles
|
22
|
+
include BuildMatrixParser
|
23
|
+
|
24
|
+
def rewrite_travis_content(content, current_file_list, &block)
|
25
|
+
env_matrix = BuildMatrixParser.parse_env_matrix(content)
|
26
|
+
original = extract_spec_files(env_matrix)
|
27
|
+
after_removed = delete_removed_files(original, current_file_list)
|
28
|
+
after_added = add_new_files(original, after_removed, current_file_list)
|
29
|
+
|
30
|
+
env_matrix.each do |var_hash|
|
31
|
+
if var_hash.has_key?('TEST_SUITE')
|
32
|
+
test_bucket = after_added.shift
|
33
|
+
|
34
|
+
var_hash['TEST_SUITE'] = "#{test_bucket.join(' ')}"
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
content['env']['matrix'] = BuildMatrixParser.format_matrix(env_matrix)
|
39
|
+
|
40
|
+
block.call(original) if block
|
41
|
+
end
|
42
|
+
|
43
|
+
module_function :rewrite_travis_content
|
44
|
+
|
45
|
+
private
|
46
|
+
|
47
|
+
def self.extract_spec_files(env_matrix)
|
48
|
+
test_suites = env_matrix.map do |var_hash|
|
49
|
+
var_hash.has_key?('TEST_SUITE') ? var_hash['TEST_SUITE'].gsub('"', '').split(' ') : nil
|
50
|
+
end
|
51
|
+
test_suites.compact
|
52
|
+
end
|
53
|
+
|
54
|
+
def self.delete_removed_files(original, current_file_list)
|
55
|
+
deleted_files = deleted_files(original, current_file_list)
|
56
|
+
|
57
|
+
original.map do |bucket|
|
58
|
+
bucket.reject { |spec_file| deleted_files.include?(spec_file) }
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
def self.add_new_files(original, buckets, current_file_list)
|
63
|
+
buckets_clone = buckets.map(&:dup)
|
64
|
+
|
65
|
+
added_files(original, current_file_list).each do |spec_file|
|
66
|
+
buckets_clone.last << spec_file
|
67
|
+
end
|
68
|
+
|
69
|
+
buckets_clone
|
70
|
+
end
|
71
|
+
|
72
|
+
def self.deleted_files(original, current_file_list)
|
73
|
+
original.flatten - current_file_list
|
74
|
+
end
|
75
|
+
|
76
|
+
def self.added_files(original, current_file_list)
|
77
|
+
current_file_list - original.flatten
|
78
|
+
end
|
79
|
+
|
80
|
+
def self.write_to_file(content)
|
81
|
+
File.open('.travis.yml', 'w') { |file| file.write(content.to_yaml(:line_width => -1)) }
|
82
|
+
end
|
83
|
+
|
84
|
+
def self.file_diff(original, current_file_list)
|
85
|
+
removed_files = deleted_files(original, current_file_list).sort
|
86
|
+
removed = removed_files.empty? ? 'No spec files removed' : removed_files
|
87
|
+
|
88
|
+
added_files = added_files(original, current_file_list).sort
|
89
|
+
added = added_files.empty? ? 'No spec files added' : added_files
|
90
|
+
|
91
|
+
" Removed: #{removed}\n Added: #{added}\n\n"
|
92
|
+
end
|
93
|
+
end
|
data/lib/spec_tiller.rb
ADDED
@@ -0,0 +1,62 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'yaml'
|
3
|
+
|
4
|
+
describe BuildMatrixParser do
|
5
|
+
|
6
|
+
let(:travis_yml_file) { YAML::load(File.open('spec/documents/.travis.yml')) }
|
7
|
+
|
8
|
+
describe '#parse_env_matrix' do
|
9
|
+
let(:actual_parsed_matrix) { BuildMatrixParser.parse_env_matrix(travis_yml_file) }
|
10
|
+
|
11
|
+
it 'will maintain same number of elements' do
|
12
|
+
expect(actual_parsed_matrix.length).to eq(5)
|
13
|
+
end
|
14
|
+
|
15
|
+
it 'will parse multiple variables' do
|
16
|
+
expect(actual_parsed_matrix[0]).to eq( { "TEST_SUITE" => "spec/features/three_vars.rb", "RUN_JS" => "true", "FAKE_VAR" => "fake.value.rb" } )
|
17
|
+
end
|
18
|
+
|
19
|
+
it 'will ignore extra spaces' do
|
20
|
+
expect(actual_parsed_matrix[1]).to eq( { "TEST_SUITE" => "spec/features/space_after.rb spec/features/space_before.rb", "FIVE_TABS_BEFORE" => "tabs are ignored" } )
|
21
|
+
end
|
22
|
+
|
23
|
+
it 'will parse lowercase, numbers, and symbols' do
|
24
|
+
expect(actual_parsed_matrix[2]).to eq( { "l0w3rC@5e&nUm5&sym()1s" => "~!@#$%^&*()_+1234567890-=`{}[]|:;''<>,.?/", "TEST_SUITE" => "spec/features/test.rb" } )
|
25
|
+
end
|
26
|
+
|
27
|
+
it 'will parse empty lines' do
|
28
|
+
expect(actual_parsed_matrix[3]).to eq( {} )
|
29
|
+
end
|
30
|
+
|
31
|
+
it 'will parse long file lists' do
|
32
|
+
expect(actual_parsed_matrix[4]).to eq( { "TEST_SUITE" => "spec/test/test1.rb spec/test/test2.rb spec/test/test3.rb spec/test/test4.rb spec/test/test5.rb spec/test/test6.rb spec/test/test7.rb spec/test/test8.rb spec/test/test9.rb spec/test/test10.rb spec/test/test11.rb spec/test/test12.rb spec/test/test13.rb spec/test/test14.rb spec/test/test15.rb spec/test/test16.rb" } )
|
33
|
+
end
|
34
|
+
|
35
|
+
end
|
36
|
+
|
37
|
+
describe '#format_matrix' do
|
38
|
+
let(:actual_formatted_matrix) { BuildMatrixParser.format_matrix(BuildMatrixParser.parse_env_matrix(travis_yml_file)) }
|
39
|
+
|
40
|
+
it 'will maintain multiple variables' do
|
41
|
+
expect(actual_formatted_matrix[0]).to eq(%Q(TEST_SUITE="spec/features/three_vars.rb" RUN_JS="true" FAKE_VAR="fake.value.rb"))
|
42
|
+
end
|
43
|
+
|
44
|
+
it 'will strip spaces' do
|
45
|
+
expect(actual_formatted_matrix[1]).to eq(%Q(TEST_SUITE="spec/features/space_after.rb spec/features/space_before.rb" FIVE_TABS_BEFORE="tabs are ignored"))
|
46
|
+
end
|
47
|
+
|
48
|
+
it 'will maintain lowercase, numbers, and symbols' do
|
49
|
+
expect(actual_formatted_matrix[2]).to eq(%Q(l0w3rC@5e&nUm5&sym()1s="~!@#$%^&*()_+1234567890-=`{}[]|:;''<>,.?/" TEST_SUITE="spec/features/test.rb"))
|
50
|
+
end
|
51
|
+
|
52
|
+
it 'will remove empty lines' do
|
53
|
+
expect(actual_formatted_matrix[3]).to_not eq(nil)
|
54
|
+
end
|
55
|
+
|
56
|
+
it 'will maintain long file lists' do
|
57
|
+
expect(actual_formatted_matrix[3]).to eq(%Q(TEST_SUITE="spec/test/test1.rb spec/test/test2.rb spec/test/test3.rb spec/test/test4.rb spec/test/test5.rb spec/test/test6.rb spec/test/test7.rb spec/test/test8.rb spec/test/test9.rb spec/test/test10.rb spec/test/test11.rb spec/test/test12.rb spec/test/test13.rb spec/test/test14.rb spec/test/test15.rb spec/test/test16.rb"))
|
58
|
+
end
|
59
|
+
|
60
|
+
end
|
61
|
+
|
62
|
+
end
|
@@ -0,0 +1,162 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'yaml'
|
3
|
+
|
4
|
+
describe 'TravisBuildMatrix' do
|
5
|
+
|
6
|
+
describe 'TestBucket' do
|
7
|
+
let(:bucket) { TravisBuildMatrix::TestBucket.new }
|
8
|
+
|
9
|
+
describe '::new' do
|
10
|
+
|
11
|
+
it 'will have an initial duration of 0.0' do
|
12
|
+
expect(bucket.total_duration).to eq(0.0)
|
13
|
+
end
|
14
|
+
|
15
|
+
it 'will begin with an empty file list' do
|
16
|
+
expect(bucket.spec_files).to eq([])
|
17
|
+
end
|
18
|
+
|
19
|
+
end
|
20
|
+
|
21
|
+
describe '#add_to_list' do
|
22
|
+
let(:short_spec_file) { TravisBuildMatrix::SpecFile.new('spec/features/short_spec_file.rb', 3.2) }
|
23
|
+
let(:long_spec_file) { TravisBuildMatrix::SpecFile.new('spec/features/long_spec_file.rb', 10.4) }
|
24
|
+
before(:each) do
|
25
|
+
bucket.add_to_list(short_spec_file)
|
26
|
+
bucket.add_to_list(long_spec_file)
|
27
|
+
end
|
28
|
+
|
29
|
+
it 'adds to bucket duration' do
|
30
|
+
expect(bucket.total_duration.round(1)).to eq(13.6)
|
31
|
+
end
|
32
|
+
|
33
|
+
it 'adds all files' do
|
34
|
+
expect(bucket.spec_files.length).to eq(2)
|
35
|
+
end
|
36
|
+
|
37
|
+
it 'maintains file order' do
|
38
|
+
expect(bucket.spec_files.first).to be(short_spec_file)
|
39
|
+
end
|
40
|
+
|
41
|
+
end
|
42
|
+
|
43
|
+
end
|
44
|
+
|
45
|
+
describe 'SpecDistributor' do
|
46
|
+
let!(:travis_yml_file) { YAML::load(File.open('spec/documents/.travis.yml')) }
|
47
|
+
let(:profile_results) { File.read('spec/documents/rspec_profile_results.txt') }
|
48
|
+
|
49
|
+
describe '::new' do
|
50
|
+
|
51
|
+
it 'defaults to 5 builds' do
|
52
|
+
travis_yml_file['num_builds'] = nil
|
53
|
+
TravisBuildMatrix::SpecDistributor.new(travis_yml_file, profile_results)
|
54
|
+
expect(travis_yml_file['env']['matrix'].length).to eq(5)
|
55
|
+
end
|
56
|
+
|
57
|
+
it 'runs when there are more builds than specs' do
|
58
|
+
travis_yml_file['num_builds'] = 20
|
59
|
+
TravisBuildMatrix::SpecDistributor.new(travis_yml_file, profile_results)
|
60
|
+
expect(travis_yml_file['env']['matrix'].length).to eq(10) # 10 is the number of builds in profile results.
|
61
|
+
end
|
62
|
+
|
63
|
+
it 'can find special characters' do
|
64
|
+
travis_yml_file['num_builds'] = 1
|
65
|
+
TravisBuildMatrix::SpecDistributor.new(travis_yml_file, profile_results)
|
66
|
+
expect(travis_yml_file['env']['matrix'].first).to include(%Q(~!@#$^()_+1234567890-=`{}[];',_spec.rb))
|
67
|
+
end
|
68
|
+
|
69
|
+
it 'groups builds as expected' do
|
70
|
+
travis_yml_file['num_builds'] = 5
|
71
|
+
TravisBuildMatrix::SpecDistributor.new(travis_yml_file, profile_results)
|
72
|
+
formatted_matrix = travis_yml_file['env']['matrix']
|
73
|
+
expect(formatted_matrix[0]).to include('different_ending.rb')
|
74
|
+
expect(formatted_matrix[1]).to include('peanut_spec.rb')
|
75
|
+
expect(formatted_matrix[2]).to include('almond_spec.rb')
|
76
|
+
expect(formatted_matrix[3]).to include('cashew_spec.rb')
|
77
|
+
expect(formatted_matrix[4]).to include(%Q(~!@#$^()_+1234567890-=`{}[];',_spec.rb))
|
78
|
+
expect(formatted_matrix[4]).to include('different_extension_spec.txt')
|
79
|
+
expect(formatted_matrix[3]).to include('pecan_spec.rb')
|
80
|
+
expect(formatted_matrix[4]).to include('walnut_spec.rb')
|
81
|
+
expect(formatted_matrix[3]).to include('acorn_spec.rb')
|
82
|
+
expect(formatted_matrix[3]).to include('pistachio_spec.rb')
|
83
|
+
end
|
84
|
+
|
85
|
+
end
|
86
|
+
|
87
|
+
end
|
88
|
+
|
89
|
+
describe 'TravisFile' do
|
90
|
+
|
91
|
+
describe '::new' do
|
92
|
+
|
93
|
+
def create_bucket(total_duration, spec_file_list)
|
94
|
+
bucket = TravisBuildMatrix::TestBucket.new
|
95
|
+
bucket.instance_variable_set("@total_duration", total_duration)
|
96
|
+
spec_file_hashes = spec_file_list.map do |file|
|
97
|
+
TravisBuildMatrix::SpecFile.new(file, 0) # don't care about duration, not used in this test
|
98
|
+
end
|
99
|
+
bucket.instance_variable_set("@spec_files", spec_file_hashes)
|
100
|
+
bucket
|
101
|
+
end
|
102
|
+
|
103
|
+
let!(:travis_yml_file) { YAML::load(File.open('spec/documents/.travis.yml')) }
|
104
|
+
|
105
|
+
let(:test_buckets) do
|
106
|
+
[create_bucket(8, ['spec/features/three_vars.rb']),
|
107
|
+
create_bucket(8.3, ['spec/features/space_after.rb', 'spec/features/space_before.rb']),
|
108
|
+
create_bucket(11.8, ['spec/features/test.rb']),
|
109
|
+
create_bucket(10.7, ['spec/test/test1.rb', 'spec/test/test2.rb', 'spec/test/test3.rb', 'spec/test/test4.rb', 'spec/test/test5.rb', 'spec/test/test6.rb', 'spec/test/test7.rb', 'spec/test/test8.rb', 'spec/test/test9.rb', 'spec/test/test10.rb', 'spec/test/test11.rb', 'spec/test/test12.rb', 'spec/test/test13.rb', 'spec/test/test14.rb', 'spec/test/test15.rb', 'spec/test/test16.rb']),
|
110
|
+
create_bucket(10.4, ['spec/features/long_spec.rb']),
|
111
|
+
create_bucket(9.1, ['spec/features/short_1_spec.rb', 'spec/features/short_2_spec.rb', 'spec/features/short_3_spec.rb'])]
|
112
|
+
end
|
113
|
+
|
114
|
+
context 'buckets are removed' do
|
115
|
+
before(:each) do
|
116
|
+
TravisBuildMatrix::TravisFile.new(test_buckets[0..1], travis_yml_file)
|
117
|
+
end
|
118
|
+
|
119
|
+
it 'compresses to the appropriate size' do
|
120
|
+
expect(travis_yml_file['env']['matrix'].length).to eq(2)
|
121
|
+
end
|
122
|
+
|
123
|
+
it 'maintains env variables within range' do
|
124
|
+
formatted_matrix = travis_yml_file['env']['matrix']
|
125
|
+
expect(formatted_matrix[0]).to include(%Q(RUN_JS="true"))
|
126
|
+
expect(formatted_matrix[0]).to include(%Q(FAKE_VAR="fake.value.rb"))
|
127
|
+
expect(formatted_matrix[1]).to include(%Q(FIVE_TABS_BEFORE="tabs are ignored"))
|
128
|
+
end
|
129
|
+
|
130
|
+
it 'drops env variables outside of range' do
|
131
|
+
travis_yml_file['env']['matrix'].each do |line|
|
132
|
+
expect(line).to_not include(%Q(l0w3rC@5e&nUm5&sym()1s="~!@#$%^&*()_+1234567890-=`{}[]|:;''<>,.?/"))
|
133
|
+
end
|
134
|
+
|
135
|
+
end
|
136
|
+
|
137
|
+
end
|
138
|
+
|
139
|
+
context 'buckets are added' do
|
140
|
+
before(:each) do
|
141
|
+
TravisBuildMatrix::TravisFile.new(test_buckets, travis_yml_file)
|
142
|
+
end
|
143
|
+
|
144
|
+
it 'expands to appropriate size' do
|
145
|
+
expect(travis_yml_file['env']['matrix'].length).to eq(6)
|
146
|
+
end
|
147
|
+
|
148
|
+
it 'maintains env variables within range' do
|
149
|
+
formatted_matrix = travis_yml_file['env']['matrix']
|
150
|
+
expect(formatted_matrix[0]).to include(%Q(RUN_JS="true"))
|
151
|
+
expect(formatted_matrix[0]).to include(%Q(FAKE_VAR="fake.value.rb"))
|
152
|
+
expect(formatted_matrix[1]).to include(%Q(FIVE_TABS_BEFORE="tabs are ignored"))
|
153
|
+
expect(formatted_matrix[2]).to include(%Q(l0w3rC@5e&nUm5&sym()1s="~!@#$%^&*()_+1234567890-=`{}[]|:;''<>,.?/"))
|
154
|
+
end
|
155
|
+
|
156
|
+
end
|
157
|
+
|
158
|
+
end
|
159
|
+
|
160
|
+
end
|
161
|
+
|
162
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
---
|
2
|
+
language: ruby
|
3
|
+
rvm:
|
4
|
+
- 2.1.2
|
5
|
+
addons:
|
6
|
+
hosts:
|
7
|
+
- example.com
|
8
|
+
branches:
|
9
|
+
only:
|
10
|
+
- develop
|
11
|
+
- master
|
12
|
+
- "/^release\\/.*$/"
|
13
|
+
- "/^hotfix\\/.*$/"
|
14
|
+
- "/^feature\\/testing-.+$/"
|
15
|
+
cache: bundler
|
16
|
+
before_install:
|
17
|
+
- export DISPLAY=:99.0
|
18
|
+
- "/sbin/start-stop-daemon --start --quiet --pidfile /tmp/custom_xvfb_99.pid --make-pidfile --background --exec /usr/bin/Xvfb -- :99 -ac -screen 0 1920x1080x16"
|
19
|
+
before_script:
|
20
|
+
- psql -c 'create database test;' -U postgres
|
21
|
+
- RAILS_ENV=test bundle exec rake --trace db:test:load db:seed
|
22
|
+
script:
|
23
|
+
- RSPEC_RETRY_COUNT=2 bundle exec rspec $TEST_SUITE --tag ~local_only
|
24
|
+
- if [[ $RUN_JS == "true" ]]; then bundle exec rake jasmine:ci; fi
|
25
|
+
env:
|
26
|
+
global:
|
27
|
+
- RUBY_GC_HEAP_OLDOBJECT_LIMIT_FACTOR=1.1
|
28
|
+
matrix:
|
29
|
+
- TEST_SUITE="spec/features/three_vars.rb" RUN_JS="true" FAKE_VAR="fake.value.rb"
|
30
|
+
- TEST_SUITE="spec/features/space_after.rb spec/features/space_before.rb" FIVE_TABS_BEFORE="tabs are ignored"
|
31
|
+
- l0w3rC@5e&nUm5&sym()1s="~!@#$%^&*()_+1234567890-=`{}[]|:;''<>,.?/" TEST_SUITE="spec/features/test.rb"
|
32
|
+
-
|
33
|
+
- TEST_SUITE="spec/test/test1.rb spec/test/test2.rb spec/test/test3.rb spec/test/test4.rb spec/test/test5.rb spec/test/test6.rb spec/test/test7.rb spec/test/test8.rb spec/test/test9.rb spec/test/test10.rb spec/test/test11.rb spec/test/test12.rb spec/test/test13.rb spec/test/test14.rb spec/test/test15.rb spec/test/test16.rb"
|
34
|
+
num_builds: 10
|
@@ -0,0 +1,23 @@
|
|
1
|
+
Below is the relevant part of profile results:
|
2
|
+
|
3
|
+
Top 10 slowest example groups:
|
4
|
+
Walnut
|
5
|
+
0.35161 seconds average (42.19 seconds / 120 examples) ./spec/feature/walnut_spec.rb:4
|
6
|
+
Acorn
|
7
|
+
0.1916 seconds average (4.6 seconds / 24 examples) ./spec/models/acorn_spec.rb:3
|
8
|
+
Pistachio
|
9
|
+
0.00297 seconds average (0.06826 seconds / 23 examples) ./spec/lib/pistachio_spec.rb:3
|
10
|
+
Cashew
|
11
|
+
12.55 seconds average (87.85 seconds / 7 examples) ./spec/features/cashew_spec.rb:3
|
12
|
+
Peanut
|
13
|
+
12.22 seconds average (305.54 seconds / 25 examples) ./spec/features/peanut_spec.rb:102
|
14
|
+
Pecan
|
15
|
+
12.17 seconds average (48.68 seconds / 4 examples) ./spec/features/pecan_spec.rb:3
|
16
|
+
Almond
|
17
|
+
11.8 seconds average (259.54 seconds / 22 examples) ./spec/features/almond_spec.rb:84
|
18
|
+
Special Chars
|
19
|
+
11.55 seconds average (69.28 seconds / 6 examples) ./spec/features/~!@#$^()_+1234567890-=`{}[];',_spec.rb:3
|
20
|
+
Different Ending
|
21
|
+
11.43 seconds average (331.49 seconds / 29 examples) ./spec/features/different_ending.rb:3
|
22
|
+
Different Extension
|
23
|
+
11.16 seconds average (66.98 seconds / 6 examples) ./spec/features/different_extension_spec.txt:3
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,48 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'yaml'
|
3
|
+
|
4
|
+
describe 'SyncSpecFiles' do
|
5
|
+
|
6
|
+
describe '#rewrite_travis_content' do
|
7
|
+
|
8
|
+
let(:current_file_list) do
|
9
|
+
['spec/test/new3.rb',
|
10
|
+
'spec/features/space_after.rb', 'spec/features/space_before.rb',
|
11
|
+
'spec/test/test1.rb', 'spec/test/test2.rb', 'spec/test/test3.rb', 'spec/test/test4.rb', 'spec/test/test5.rb', 'spec/test/test6.rb', 'spec/test/test7.rb', 'spec/test/test8.rb', 'spec/test/test9.rb', 'spec/test/test10.rb', 'spec/test/test11.rb', 'spec/test/test12.rb', 'spec/test/test13.rb', 'spec/test/test14.rb', 'spec/test/test15.rb', 'spec/test/test16.rb',
|
12
|
+
'spec/test/new1.rb', 'spec/test2/new2.rb']
|
13
|
+
end
|
14
|
+
let(:travis_yaml) { YAML::load(File.open('spec/documents/.travis.yml')) }
|
15
|
+
|
16
|
+
before(:each) do
|
17
|
+
SyncSpecFiles.rewrite_travis_content(travis_yaml, current_file_list)
|
18
|
+
end
|
19
|
+
|
20
|
+
it 'adds new files to the last line' do
|
21
|
+
last_line = travis_yaml['env']['matrix'].last
|
22
|
+
|
23
|
+
expect(last_line).to include('spec/test/new1.rb','spec/test2/new2.rb','spec/test/new3.rb')
|
24
|
+
end
|
25
|
+
|
26
|
+
it "doesn't add new files to other lines" do
|
27
|
+
travis_yaml['env']['matrix'][0..-2].each do |bucket|
|
28
|
+
expect(bucket).not_to include('spec/test/new1.rb')
|
29
|
+
expect(bucket).not_to include('spec/test2/new2.rb')
|
30
|
+
expect(bucket).not_to include('spec/test/new3.rb')
|
31
|
+
end
|
32
|
+
|
33
|
+
end
|
34
|
+
|
35
|
+
it 'removes unused specs' do
|
36
|
+
travis_yaml['env']['matrix'].each do |bucket|
|
37
|
+
expect(bucket).not_to include('spec/features/three_vars.rb')
|
38
|
+
end
|
39
|
+
|
40
|
+
end
|
41
|
+
|
42
|
+
it 'removes unused buckets' do
|
43
|
+
expect(travis_yaml['env']['matrix'].length).to eq(2)
|
44
|
+
end
|
45
|
+
|
46
|
+
end
|
47
|
+
|
48
|
+
end
|
data/spec_tiller.gemspec
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'spec_tiller/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "spec_tiller"
|
8
|
+
spec.version = SpecTiller::VERSION
|
9
|
+
spec.authors = ["Matt Schmaus","Josh Bazemore"]
|
10
|
+
spec.email = ["mschmaus201@gmail.com","jbazemore@greenhouse.io"]
|
11
|
+
spec.description = <<-EOF
|
12
|
+
This gem will parse the output of calling "rspec --perform", then will redistribute
|
13
|
+
the spec files evenly, based on file run time, across all builds established
|
14
|
+
in the travis.yml file.
|
15
|
+
EOF
|
16
|
+
spec.summary = 'Distribute spec files evenly across Travis builds, based on file run time'
|
17
|
+
spec.homepage = ""
|
18
|
+
spec.license = "MIT"
|
19
|
+
|
20
|
+
spec.files = `git ls-files`.split($/)
|
21
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
22
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
23
|
+
spec.require_paths = ["lib"]
|
24
|
+
|
25
|
+
spec.add_development_dependency "bundler", "~> 1.3"
|
26
|
+
spec.add_development_dependency "rake"
|
27
|
+
spec.add_development_dependency "rspec"
|
28
|
+
end
|
metadata
CHANGED
@@ -1,52 +1,86 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: spec_tiller
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 1.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Matt Schmaus
|
8
|
+
- Josh Bazemore
|
8
9
|
autorequire:
|
9
10
|
bindir: bin
|
10
11
|
cert_chain: []
|
11
|
-
date: 2014-
|
12
|
+
date: 2014-11-20 00:00:00.000000000 Z
|
12
13
|
dependencies:
|
13
14
|
- !ruby/object:Gem::Dependency
|
14
15
|
name: bundler
|
15
16
|
requirement: !ruby/object:Gem::Requirement
|
16
17
|
requirements:
|
17
|
-
- - ~>
|
18
|
+
- - "~>"
|
18
19
|
- !ruby/object:Gem::Version
|
19
20
|
version: '1.3'
|
20
21
|
type: :development
|
21
22
|
prerelease: false
|
22
23
|
version_requirements: !ruby/object:Gem::Requirement
|
23
24
|
requirements:
|
24
|
-
- - ~>
|
25
|
+
- - "~>"
|
25
26
|
- !ruby/object:Gem::Version
|
26
27
|
version: '1.3'
|
27
28
|
- !ruby/object:Gem::Dependency
|
28
29
|
name: rake
|
29
30
|
requirement: !ruby/object:Gem::Requirement
|
30
31
|
requirements:
|
31
|
-
- -
|
32
|
+
- - ">="
|
32
33
|
- !ruby/object:Gem::Version
|
33
34
|
version: '0'
|
34
35
|
type: :development
|
35
36
|
prerelease: false
|
36
37
|
version_requirements: !ruby/object:Gem::Requirement
|
37
38
|
requirements:
|
38
|
-
- -
|
39
|
+
- - ">="
|
39
40
|
- !ruby/object:Gem::Version
|
40
41
|
version: '0'
|
41
|
-
|
42
|
-
|
43
|
-
|
42
|
+
- !ruby/object:Gem::Dependency
|
43
|
+
name: rspec
|
44
|
+
requirement: !ruby/object:Gem::Requirement
|
45
|
+
requirements:
|
46
|
+
- - ">="
|
47
|
+
- !ruby/object:Gem::Version
|
48
|
+
version: '0'
|
49
|
+
type: :development
|
50
|
+
prerelease: false
|
51
|
+
version_requirements: !ruby/object:Gem::Requirement
|
52
|
+
requirements:
|
53
|
+
- - ">="
|
54
|
+
- !ruby/object:Gem::Version
|
55
|
+
version: '0'
|
56
|
+
description: |2
|
57
|
+
This gem will parse the output of calling "rspec --perform", then will redistribute
|
58
|
+
the spec files evenly, based on file run time, across all builds established
|
59
|
+
in the travis.yml file.
|
44
60
|
email:
|
45
61
|
- mschmaus201@gmail.com
|
62
|
+
- jbazemore@greenhouse.io
|
46
63
|
executables: []
|
47
64
|
extensions: []
|
48
65
|
extra_rdoc_files: []
|
49
|
-
files:
|
66
|
+
files:
|
67
|
+
- ".gitignore"
|
68
|
+
- Gemfile
|
69
|
+
- LICENSE.txt
|
70
|
+
- README.md
|
71
|
+
- Rakefile
|
72
|
+
- lib/spec_tiller.rb
|
73
|
+
- lib/spec_tiller/build_matrix_parser.rb
|
74
|
+
- lib/spec_tiller/distribute_spec_files.rb
|
75
|
+
- lib/spec_tiller/sync_spec_file_list.rb
|
76
|
+
- lib/spec_tiller/version.rb
|
77
|
+
- spec/build_matrix_parser_spec.rb
|
78
|
+
- spec/distribute_spec_files_spec.rb
|
79
|
+
- spec/documents/.travis.yml
|
80
|
+
- spec/documents/rspec_profile_results.txt
|
81
|
+
- spec/spec_helper.rb
|
82
|
+
- spec/sync_spec_file_list_spec.rb
|
83
|
+
- spec_tiller.gemspec
|
50
84
|
homepage: ''
|
51
85
|
licenses:
|
52
86
|
- MIT
|
@@ -57,18 +91,24 @@ require_paths:
|
|
57
91
|
- lib
|
58
92
|
required_ruby_version: !ruby/object:Gem::Requirement
|
59
93
|
requirements:
|
60
|
-
- -
|
94
|
+
- - ">="
|
61
95
|
- !ruby/object:Gem::Version
|
62
96
|
version: '0'
|
63
97
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
64
98
|
requirements:
|
65
|
-
- -
|
99
|
+
- - ">="
|
66
100
|
- !ruby/object:Gem::Version
|
67
101
|
version: '0'
|
68
102
|
requirements: []
|
69
103
|
rubyforge_project:
|
70
|
-
rubygems_version: 2.
|
104
|
+
rubygems_version: 2.2.2
|
71
105
|
signing_key:
|
72
106
|
specification_version: 4
|
73
107
|
summary: Distribute spec files evenly across Travis builds, based on file run time
|
74
|
-
test_files:
|
108
|
+
test_files:
|
109
|
+
- spec/build_matrix_parser_spec.rb
|
110
|
+
- spec/distribute_spec_files_spec.rb
|
111
|
+
- spec/documents/.travis.yml
|
112
|
+
- spec/documents/rspec_profile_results.txt
|
113
|
+
- spec/spec_helper.rb
|
114
|
+
- spec/sync_spec_file_list_spec.rb
|