test_suite_splitter 0.0.2 → 0.0.4
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/README.md +30 -1
- data/Rakefile +10 -0
- data/bin/test_suite_splitter +1 -23
- data/bin/test_suite_splitter_rspec +5 -0
- data/lib/test_suite_splitter/cli.rb +124 -0
- data/lib/test_suite_splitter/release.rb +69 -0
- data/lib/test_suite_splitter/rspec_helper.rb +36 -11
- data/lib/test_suite_splitter.rb +2 -0
- metadata +49 -6
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 2bf5b723c5f3b7bc866531725c9d7127fdca1277d5c53079e9bb2751817342fc
|
|
4
|
+
data.tar.gz: 35b104aca369d17a0b256a732bb7aaa4c73eb60a7dfa3f028eec5c1d497ada40
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: '08ae2c9be973a1b14b893ecc9517794ecf297d02aac5a8825346511803274edffd6866c01778fa460ca4c6d6d175c8735dbe19190a7b55a6654ccd5c3da3ec89'
|
|
7
|
+
data.tar.gz: 9138c299cd2fe61f270a57d6982e24a5ef9e2a66b35aa99b041aa3830925b6473efeaf45d7b46d21a3f42a15d3a04b2de819870dcf8ea8abb2606bb3c73ce4e7
|
data/README.md
CHANGED
|
@@ -12,11 +12,40 @@ Change your CI configuration file to execute something like this:
|
|
|
12
12
|
bundle exec rspec `bundle exec test_suite_splitter --groups=6 --group-number=3`
|
|
13
13
|
```
|
|
14
14
|
|
|
15
|
-
Or
|
|
15
|
+
Or let `test_suite_splitter` run RSpec directly:
|
|
16
|
+
```bash
|
|
17
|
+
bundle exec test_suite_splitter_rspec --groups=6 --group-number=3 -- --format documentation
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
On Semaphore that could be done dynamically like this:
|
|
16
21
|
```bash
|
|
17
22
|
bundle exec rspec `bundle exec test_suite_splitter --groups=${SEMAPHORE_JOB_COUNT} --group-number=${SEMAPHORE_JOB_INDEX}`
|
|
18
23
|
```
|
|
19
24
|
|
|
25
|
+
Run only a certain type of specs:
|
|
26
|
+
```bash
|
|
27
|
+
bundle exec rspec `bundle exec test_suite_splitter --groups=6 --group-number=3 --only-types=system,model`
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
Exclude a certain type of specs:
|
|
31
|
+
```bash
|
|
32
|
+
bundle exec rspec `bundle exec test_suite_splitter --groups=6 --group-number=3 --exclude-types=system,feature`
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
Exclude file paths by prefix:
|
|
36
|
+
```bash
|
|
37
|
+
bundle exec test_suite_splitter_rspec --groups=6 --group-number=3 --exclude-path-prefixes=spec/system/projects/project_environments_terminal_e2e_spec/ -- --format documentation
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
When the dry run fails, `test_suite_splitter` writes the failure output to `log/test_suite_splitter.log` by default. Override that path with `--log-file=path/to/file.log`.
|
|
41
|
+
|
|
42
|
+
Release a new gem version:
|
|
43
|
+
```bash
|
|
44
|
+
bundle exec rake release:patch
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
`release:path` is available as an alias for the same flow.
|
|
48
|
+
|
|
20
49
|
## Contributing to test_suite_splitter
|
|
21
50
|
|
|
22
51
|
* Check out the latest master to make sure the feature hasn't been implemented or the bug hasn't been fixed yet.
|
data/Rakefile
CHANGED
|
@@ -8,6 +8,7 @@ rescue Bundler::BundlerError => e
|
|
|
8
8
|
exit e.status_code
|
|
9
9
|
end
|
|
10
10
|
require "rake"
|
|
11
|
+
require_relative "lib/test_suite_splitter"
|
|
11
12
|
task default: :test
|
|
12
13
|
|
|
13
14
|
require "rdoc/task"
|
|
@@ -19,3 +20,12 @@ Rake::RDocTask.new do |rdoc|
|
|
|
19
20
|
rdoc.rdoc_files.include("README*")
|
|
20
21
|
rdoc.rdoc_files.include("lib/**/*.rb")
|
|
21
22
|
end
|
|
23
|
+
|
|
24
|
+
namespace :release do
|
|
25
|
+
desc "Bump the patch version, commit it, push master, build the gem, and push it"
|
|
26
|
+
task :patch do
|
|
27
|
+
TestSuiteSplitter::Release.call(part: :patch)
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
task path: :patch
|
|
31
|
+
end
|
data/bin/test_suite_splitter
CHANGED
|
@@ -4,26 +4,4 @@
|
|
|
4
4
|
|
|
5
5
|
require "#{__dir__}/../lib/test_suite_splitter"
|
|
6
6
|
|
|
7
|
-
|
|
8
|
-
ARGV.each do |arg|
|
|
9
|
-
match = arg.match(/\A--(.+?)=(.+)\Z/)
|
|
10
|
-
raise "Couldn't match argument: #{arg}" unless match
|
|
11
|
-
|
|
12
|
-
key = match[1]
|
|
13
|
-
hash_key = key.tr("-", "_").to_sym
|
|
14
|
-
value = match[2]
|
|
15
|
-
|
|
16
|
-
if key == "exclude-types" || key == "only-types" || key == "tags"
|
|
17
|
-
value = value.split(",")
|
|
18
|
-
elsif key == "group-number" || key == "groups"
|
|
19
|
-
value = value.to_i
|
|
20
|
-
else
|
|
21
|
-
raise "Unknown argument: #{key}"
|
|
22
|
-
end
|
|
23
|
-
|
|
24
|
-
args[hash_key] = value
|
|
25
|
-
end
|
|
26
|
-
|
|
27
|
-
rspec_helper = ::TestSuiteSplitter::RspecHelper.new(**args)
|
|
28
|
-
|
|
29
|
-
print rspec_helper.group_files.map { |group_file| group_file.fetch(:path) }.join(" ")
|
|
7
|
+
exit(TestSuiteSplitter::Cli.new(argv: ARGV).execute_splitter_command)
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
class TestSuiteSplitter::Cli
|
|
2
|
+
DEFAULT_LOG_FILE_PATH = "log/test_suite_splitter.log".freeze
|
|
3
|
+
|
|
4
|
+
attr_reader :argv, :stderr, :stdout
|
|
5
|
+
|
|
6
|
+
def initialize(argv:, stderr: $stderr, stdout: $stdout)
|
|
7
|
+
@argv = argv
|
|
8
|
+
@stderr = stderr
|
|
9
|
+
@stdout = stdout
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def execute_splitter_command
|
|
13
|
+
print_output(group_file_paths.join(" "))
|
|
14
|
+
0
|
|
15
|
+
rescue StandardError => e
|
|
16
|
+
handle_error(e)
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def execute_rspec_command
|
|
20
|
+
files = group_file_paths
|
|
21
|
+
|
|
22
|
+
if files.empty?
|
|
23
|
+
print_output("No files from test_suite_splitter - skipping shard")
|
|
24
|
+
return 0
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
require "rspec/core"
|
|
28
|
+
|
|
29
|
+
RSpec::Core::Runner.run(rspec_arguments + files, stderr, stdout)
|
|
30
|
+
rescue StandardError => e
|
|
31
|
+
handle_error(e)
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def group_file_paths
|
|
35
|
+
rspec_helper.group_files.map { |group_file| group_file.fetch(:path) }
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
private
|
|
39
|
+
|
|
40
|
+
def handle_error(error)
|
|
41
|
+
message = error.message
|
|
42
|
+
|
|
43
|
+
write_log(message)
|
|
44
|
+
print_output("#{message}\n\nLogged to #{log_file_path}")
|
|
45
|
+
|
|
46
|
+
1
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
def write_log(message)
|
|
50
|
+
require "fileutils"
|
|
51
|
+
|
|
52
|
+
FileUtils.mkdir_p(File.dirname(log_file_path))
|
|
53
|
+
File.write(log_file_path, "#{message}\n")
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
def print_output(message)
|
|
57
|
+
stdout.print(message)
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
def log_file_path
|
|
61
|
+
@parsed_arguments&.fetch(:log_file) || DEFAULT_LOG_FILE_PATH
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
def rspec_helper
|
|
65
|
+
@rspec_helper ||= TestSuiteSplitter::RspecHelper.new(**splitter_arguments)
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
def splitter_arguments
|
|
69
|
+
parsed_arguments.slice(:exclude_path_prefixes, :exclude_types, :group_number, :groups, :only_types, :tags)
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
def rspec_arguments
|
|
73
|
+
parsed_arguments.fetch(:rspec_arguments)
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
def parsed_arguments
|
|
77
|
+
@parsed_arguments ||= begin
|
|
78
|
+
result = {
|
|
79
|
+
exclude_path_prefixes: nil,
|
|
80
|
+
exclude_types: nil,
|
|
81
|
+
log_file: DEFAULT_LOG_FILE_PATH,
|
|
82
|
+
only_types: nil,
|
|
83
|
+
rspec_arguments: [],
|
|
84
|
+
tags: nil
|
|
85
|
+
}
|
|
86
|
+
parsing_splitter_arguments = true
|
|
87
|
+
|
|
88
|
+
argv.each do |arg|
|
|
89
|
+
if parsing_splitter_arguments && arg == "--"
|
|
90
|
+
parsing_splitter_arguments = false
|
|
91
|
+
next
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
if parsing_splitter_arguments
|
|
95
|
+
key, value = parse_argument(arg)
|
|
96
|
+
result[key] = value
|
|
97
|
+
else
|
|
98
|
+
result[:rspec_arguments] << arg
|
|
99
|
+
end
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
result
|
|
103
|
+
end
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
def parse_argument(argument)
|
|
107
|
+
match = argument.match(/\A--(.+?)=(.+)\Z/)
|
|
108
|
+
raise "Couldn't match argument: #{argument}" unless match
|
|
109
|
+
|
|
110
|
+
key = match[1]
|
|
111
|
+
value = match[2]
|
|
112
|
+
|
|
113
|
+
case key
|
|
114
|
+
when "exclude-path-prefixes", "exclude-types", "only-types", "tags"
|
|
115
|
+
[key.tr("-", "_").to_sym, value.split(",")]
|
|
116
|
+
when "group-number", "groups"
|
|
117
|
+
[key.tr("-", "_").to_sym, value.to_i]
|
|
118
|
+
when "log-file"
|
|
119
|
+
[:log_file, value]
|
|
120
|
+
else
|
|
121
|
+
raise "Unknown argument: #{key}"
|
|
122
|
+
end
|
|
123
|
+
end
|
|
124
|
+
end
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
module TestSuiteSplitter
|
|
2
|
+
end
|
|
3
|
+
|
|
4
|
+
class TestSuiteSplitter::Release
|
|
5
|
+
VERSION_FILE = File.expand_path("../../VERSION", __dir__)
|
|
6
|
+
GEMSPEC_FILE = "test_suite_splitter.gemspec".freeze
|
|
7
|
+
MASTER_BRANCH = "master".freeze
|
|
8
|
+
|
|
9
|
+
def self.call(part: :patch)
|
|
10
|
+
new(part: part).call
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def initialize(part:)
|
|
14
|
+
@part = part.to_sym
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def call
|
|
18
|
+
next_version = bumped_version
|
|
19
|
+
write_version(next_version)
|
|
20
|
+
run("git", "commit", "VERSION", GEMSPEC_FILE, "-m", "Release #{next_version}")
|
|
21
|
+
run("git", "push", "origin", MASTER_BRANCH)
|
|
22
|
+
run("gem", "build", GEMSPEC_FILE)
|
|
23
|
+
run("gem", "push", gem_file_name(next_version))
|
|
24
|
+
next_version
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
private
|
|
28
|
+
|
|
29
|
+
attr_reader :part
|
|
30
|
+
|
|
31
|
+
def bumped_version
|
|
32
|
+
case part
|
|
33
|
+
when :patch, :path
|
|
34
|
+
major, minor, patch = current_version_segments
|
|
35
|
+
[major, minor, patch + 1].join(".")
|
|
36
|
+
else
|
|
37
|
+
raise ArgumentError, "Unsupported release part: #{part}"
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def current_version
|
|
42
|
+
File.read(VERSION_FILE).strip
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def current_version_segments
|
|
46
|
+
segments = current_version.split(".").map do |segment|
|
|
47
|
+
Integer(segment, 10)
|
|
48
|
+
rescue ArgumentError
|
|
49
|
+
raise ArgumentError, "Invalid version: #{current_version}"
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
raise ArgumentError, "Invalid version: #{current_version}" unless segments.length == 3
|
|
53
|
+
|
|
54
|
+
segments
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
def gem_file_name(version)
|
|
58
|
+
"test_suite_splitter-#{version}.gem"
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
def run(*command)
|
|
62
|
+
success = system(*command)
|
|
63
|
+
raise "Command failed: #{command.join(' ')}" unless success
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
def write_version(version)
|
|
67
|
+
File.write(VERSION_FILE, "#{version}\n")
|
|
68
|
+
end
|
|
69
|
+
end
|
|
@@ -1,13 +1,14 @@
|
|
|
1
1
|
class TestSuiteSplitter::RspecHelper
|
|
2
|
-
attr_reader :exclude_types, :only_types, :tags
|
|
2
|
+
attr_reader :exclude_path_prefixes, :exclude_types, :only_types, :tags
|
|
3
3
|
|
|
4
|
-
def initialize(groups:, group_number:,
|
|
5
|
-
@
|
|
4
|
+
def initialize(groups:, group_number:, **options)
|
|
5
|
+
@exclude_path_prefixes = options[:exclude_path_prefixes]
|
|
6
|
+
@exclude_types = options[:exclude_types]
|
|
6
7
|
@groups = groups
|
|
7
8
|
@group_number = group_number
|
|
8
9
|
@example_data_exists = File.exist?("spec/examples.txt")
|
|
9
|
-
@only_types = only_types
|
|
10
|
-
@tags = tags
|
|
10
|
+
@only_types = options[:only_types]
|
|
11
|
+
@tags = options[:tags]
|
|
11
12
|
end
|
|
12
13
|
|
|
13
14
|
def example_data_exists?
|
|
@@ -143,11 +144,11 @@ private
|
|
|
143
144
|
require "stringio"
|
|
144
145
|
|
|
145
146
|
output_capture = StringIO.new
|
|
146
|
-
RSpec::Core::Runner.run(rspec_options, $stderr, output_capture)
|
|
147
|
+
exit_code = RSpec::Core::Runner.run(rspec_options, $stderr, output_capture)
|
|
147
148
|
|
|
148
149
|
result = ::JSON.parse(output_capture.string)
|
|
149
150
|
|
|
150
|
-
raise
|
|
151
|
+
raise dry_run_error_message(result: result, exit_code: exit_code) if result.fetch("examples").empty?
|
|
151
152
|
|
|
152
153
|
result
|
|
153
154
|
end
|
|
@@ -161,11 +162,14 @@ private
|
|
|
161
162
|
@files ||= begin
|
|
162
163
|
result = {}
|
|
163
164
|
dry_result.fetch("examples").each do |example|
|
|
164
|
-
|
|
165
|
+
file_path_id = example.fetch("id")
|
|
166
|
+
file_path = file_path_id.gsub(/\[([\d:]+)\]$/, "") # Same as ID but remove any [1:2:3] at the end
|
|
167
|
+
|
|
165
168
|
file_path = file_path[2, file_path.length]
|
|
166
|
-
type = type_from_path(
|
|
169
|
+
type = type_from_path(file_path_id)
|
|
167
170
|
points = points_from_type(type)
|
|
168
171
|
|
|
172
|
+
next if ignore_path?(file_path)
|
|
169
173
|
next if ignore_type?(type)
|
|
170
174
|
|
|
171
175
|
result[file_path] = {examples: 0, path: file_path, points: 0, type: type} unless result.key?(file_path)
|
|
@@ -184,8 +188,16 @@ private
|
|
|
184
188
|
false
|
|
185
189
|
end
|
|
186
190
|
|
|
191
|
+
def ignore_path?(file_path)
|
|
192
|
+
exclude_path_prefixes&.any? do |exclude_path_prefix|
|
|
193
|
+
file_path.start_with?(exclude_path_prefix)
|
|
194
|
+
end
|
|
195
|
+
end
|
|
196
|
+
|
|
187
197
|
def points_from_type(type)
|
|
188
|
-
if type == "
|
|
198
|
+
if type == "system"
|
|
199
|
+
20
|
|
200
|
+
elsif type == "feature"
|
|
189
201
|
10
|
|
190
202
|
elsif type == "controllers"
|
|
191
203
|
3
|
|
@@ -207,8 +219,21 @@ private
|
|
|
207
219
|
rspec_options
|
|
208
220
|
end
|
|
209
221
|
|
|
222
|
+
def dry_run_error_message(result:, exit_code:)
|
|
223
|
+
error_summary = []
|
|
224
|
+
errors_outside_of_examples_count = result.dig("summary", "errors_outside_of_examples_count")
|
|
225
|
+
|
|
226
|
+
error_summary << "exit_code=#{exit_code}"
|
|
227
|
+
error_summary << "errors_outside_of_examples_count=#{errors_outside_of_examples_count}" if errors_outside_of_examples_count.to_i.positive?
|
|
228
|
+
|
|
229
|
+
first_message = result.fetch("messages", []).find { |message| message.strip != "" }
|
|
230
|
+
details = first_message&.strip || "No examples were found"
|
|
231
|
+
|
|
232
|
+
"RSpec dry-run failed (#{error_summary.join(', ')})\n\n#{details}"
|
|
233
|
+
end
|
|
234
|
+
|
|
210
235
|
def type_from_path(file_path)
|
|
211
|
-
match = file_path.match(
|
|
236
|
+
match = file_path.match(/^\.\/spec\/(.+?)\//)
|
|
212
237
|
match[1] if match
|
|
213
238
|
end
|
|
214
239
|
end
|
data/lib/test_suite_splitter.rb
CHANGED
metadata
CHANGED
|
@@ -1,15 +1,28 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: test_suite_splitter
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.0.
|
|
4
|
+
version: 0.0.4
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- kaspernj
|
|
8
|
-
autorequire:
|
|
9
8
|
bindir: bin
|
|
10
9
|
cert_chain: []
|
|
11
|
-
date:
|
|
10
|
+
date: 1980-01-02 00:00:00.000000000 Z
|
|
12
11
|
dependencies:
|
|
12
|
+
- !ruby/object:Gem::Dependency
|
|
13
|
+
name: base64
|
|
14
|
+
requirement: !ruby/object:Gem::Requirement
|
|
15
|
+
requirements:
|
|
16
|
+
- - ">="
|
|
17
|
+
- !ruby/object:Gem::Version
|
|
18
|
+
version: '0'
|
|
19
|
+
type: :development
|
|
20
|
+
prerelease: false
|
|
21
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
22
|
+
requirements:
|
|
23
|
+
- - ">="
|
|
24
|
+
- !ruby/object:Gem::Version
|
|
25
|
+
version: '0'
|
|
13
26
|
- !ruby/object:Gem::Dependency
|
|
14
27
|
name: bundler
|
|
15
28
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -24,6 +37,34 @@ dependencies:
|
|
|
24
37
|
- - ">="
|
|
25
38
|
- !ruby/object:Gem::Version
|
|
26
39
|
version: '0'
|
|
40
|
+
- !ruby/object:Gem::Dependency
|
|
41
|
+
name: racc
|
|
42
|
+
requirement: !ruby/object:Gem::Requirement
|
|
43
|
+
requirements:
|
|
44
|
+
- - ">="
|
|
45
|
+
- !ruby/object:Gem::Version
|
|
46
|
+
version: '0'
|
|
47
|
+
type: :development
|
|
48
|
+
prerelease: false
|
|
49
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
50
|
+
requirements:
|
|
51
|
+
- - ">="
|
|
52
|
+
- !ruby/object:Gem::Version
|
|
53
|
+
version: '0'
|
|
54
|
+
- !ruby/object:Gem::Dependency
|
|
55
|
+
name: rake
|
|
56
|
+
requirement: !ruby/object:Gem::Requirement
|
|
57
|
+
requirements:
|
|
58
|
+
- - ">="
|
|
59
|
+
- !ruby/object:Gem::Version
|
|
60
|
+
version: '0'
|
|
61
|
+
type: :development
|
|
62
|
+
prerelease: false
|
|
63
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
64
|
+
requirements:
|
|
65
|
+
- - ">="
|
|
66
|
+
- !ruby/object:Gem::Version
|
|
67
|
+
version: '0'
|
|
27
68
|
- !ruby/object:Gem::Dependency
|
|
28
69
|
name: rspec
|
|
29
70
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -84,6 +125,7 @@ description: Split your RSpec test suite up into several groups and run them in
|
|
|
84
125
|
email: k@spernj.org
|
|
85
126
|
executables:
|
|
86
127
|
- test_suite_splitter
|
|
128
|
+
- test_suite_splitter_rspec
|
|
87
129
|
extensions: []
|
|
88
130
|
extra_rdoc_files:
|
|
89
131
|
- LICENSE.txt
|
|
@@ -93,14 +135,16 @@ files:
|
|
|
93
135
|
- README.md
|
|
94
136
|
- Rakefile
|
|
95
137
|
- bin/test_suite_splitter
|
|
138
|
+
- bin/test_suite_splitter_rspec
|
|
96
139
|
- lib/test_suite_splitter.rb
|
|
140
|
+
- lib/test_suite_splitter/cli.rb
|
|
141
|
+
- lib/test_suite_splitter/release.rb
|
|
97
142
|
- lib/test_suite_splitter/rspec_helper.rb
|
|
98
143
|
homepage: http://github.com/kaspernj/test_suite_splitter
|
|
99
144
|
licenses:
|
|
100
145
|
- MIT
|
|
101
146
|
metadata:
|
|
102
147
|
rubygems_mfa_required: 'true'
|
|
103
|
-
post_install_message:
|
|
104
148
|
rdoc_options: []
|
|
105
149
|
require_paths:
|
|
106
150
|
- lib
|
|
@@ -115,8 +159,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
115
159
|
- !ruby/object:Gem::Version
|
|
116
160
|
version: '0'
|
|
117
161
|
requirements: []
|
|
118
|
-
rubygems_version: 3.
|
|
119
|
-
signing_key:
|
|
162
|
+
rubygems_version: 3.6.9
|
|
120
163
|
specification_version: 4
|
|
121
164
|
summary: Split your RSpec test suite up into several groups and run them in parallel.
|
|
122
165
|
test_files: []
|