semaphore_test_boosters 1.8.0 → 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 9403e453151e8b33705cd21a2d2421efd6160e30
4
- data.tar.gz: be15846080e83674e3cae45e34a8969646993228
3
+ metadata.gz: 818fb423cc0dca748176dcc676e1827e76215f86
4
+ data.tar.gz: 5829ff0d66e9613f0f9705617604dd7a447670eb
5
5
  SHA512:
6
- metadata.gz: c1383be5aba30566585ed5568ccda59ed28ad9097ee2f8f5999c614ae66133b7d145b3d69a61c1a6b10d06bfd68ec381e60caf93fa3acf93653b2d187accdab3
7
- data.tar.gz: 80d349f51e9618bc7966fb4806b4346ef4465bd075a973e6e84bd759b07e404ac7929798eab8e8ced990f835628f588f0e3035ea86f9b1b1634dbe05653cf54f
6
+ metadata.gz: 104ea0a5bb98c8479fdc8a8d6a1d73b0b5c4f71d851582b33db7176e855bd1f800c508adf3a37438ac0d3b1ad614c182de4bb0e77267fa85d399f9c2ac911637
7
+ data.tar.gz: 9029ac6ab8388faa94cb18af5487611e60f9d8c2fd4d4af9b6763e3cd45c4cb2cba704f3596995ce3c0f7702e52cd5b6398b4ea7cddf3f6fe61271cc013e35eb
@@ -2,11 +2,4 @@
2
2
 
3
3
  require "test_boosters"
4
4
 
5
- cli_options = TestBoosters::CliParser.parse
6
-
7
- job_index = cli_options[:job_index] - 1
8
- job_count = cli_options[:job_count]
9
-
10
- cucumber_booster = TestBoosters::Cucumber::Booster.new(job_index, job_count)
11
-
12
- exit(cucumber_booster.run)
5
+ exit(TestBoosters::Boosters::Cucumber.new.run)
@@ -0,0 +1,5 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "test_boosters"
4
+
5
+ exit(TestBoosters::Boosters::ExUnit.new.run)
@@ -0,0 +1,5 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "test_boosters"
4
+
5
+ exit(TestBoosters::Boosters::GoTest.new.run)
@@ -0,0 +1,5 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "test_boosters"
4
+
5
+ exit(TestBoosters::Boosters::Minitest.new.run)
@@ -2,11 +2,4 @@
2
2
 
3
3
  require "test_boosters"
4
4
 
5
- cli_options = TestBoosters::CliParser.parse
6
-
7
- job_index = cli_options[:job_index] - 1
8
- job_count = cli_options[:job_count]
9
-
10
- rspec_booster = TestBoosters::Rspec::Booster.new(job_index, job_count)
11
-
12
- exit(rspec_booster.run)
5
+ exit(TestBoosters::Boosters::Rspec.new.run)
@@ -6,17 +6,21 @@ require "cucumber_booster_config"
6
6
  module TestBoosters
7
7
  require "test_boosters/version"
8
8
 
9
- require "test_boosters/split_configuration"
10
9
  require "test_boosters/cli_parser"
11
10
  require "test_boosters/logger"
12
11
  require "test_boosters/shell"
13
- require "test_boosters/leftover_files"
14
12
  require "test_boosters/insights_uploader"
15
13
  require "test_boosters/project_info"
14
+ require "test_boosters/job"
16
15
 
17
- require "test_boosters/rspec/booster"
18
- require "test_boosters/rspec/job"
16
+ require "test_boosters/files/distributor"
17
+ require "test_boosters/files/leftover_files"
18
+ require "test_boosters/files/split_configuration"
19
19
 
20
- require "test_boosters/cucumber/booster"
21
- require "test_boosters/cucumber/job"
20
+ require "test_boosters/boosters/base"
21
+ require "test_boosters/boosters/rspec"
22
+ require "test_boosters/boosters/cucumber"
23
+ require "test_boosters/boosters/go_test"
24
+ require "test_boosters/boosters/ex_unit"
25
+ require "test_boosters/boosters/minitest"
22
26
  end
@@ -0,0 +1,65 @@
1
+ module TestBoosters
2
+ module Boosters
3
+ class Base
4
+
5
+ def initialize(file_pattern, split_configuration_path, command)
6
+ @command = command
7
+ @file_pattern = file_pattern
8
+ @split_configuration_path = split_configuration_path
9
+ end
10
+
11
+ # :reek:TooManyStatements
12
+ def run
13
+ display_header
14
+
15
+ before_job # execute some activities when the before the job starts
16
+
17
+ distribution.display_info
18
+
19
+ known, leftover = distribution.files_for(job_index)
20
+
21
+ exit_status = TestBoosters::Job.run(@command, known, leftover)
22
+
23
+ after_job # execute some activities when the job finishes
24
+
25
+ exit_status
26
+ end
27
+
28
+ def before_job
29
+ # Do nothing
30
+ end
31
+
32
+ def after_job
33
+ # Do nothing
34
+ end
35
+
36
+ def display_header
37
+ version = "Test Booster v#{TestBoosters::VERSION}"
38
+ job_info = "Job #{job_index + 1} out of #{job_count}"
39
+
40
+ TestBoosters::Shell.display_title("#{version} - #{job_info}")
41
+ end
42
+
43
+ def distribution
44
+ @distribution ||= TestBoosters::Files::Distributor.new(@split_configuration_path,
45
+ @file_pattern,
46
+ job_count)
47
+ end
48
+
49
+ def job_index
50
+ @job_index ||= cli_options[:job_index] - 1
51
+ end
52
+
53
+ def job_count
54
+ @job_count ||= cli_options[:job_count]
55
+ end
56
+
57
+ private
58
+
59
+ def cli_options
60
+ @cli_options ||= TestBoosters::CliParser.parse
61
+ end
62
+
63
+ end
64
+ end
65
+ end
@@ -0,0 +1,37 @@
1
+ module TestBoosters
2
+ module Boosters
3
+ class Cucumber < Base
4
+
5
+ FILE_PATTERN = "features/**/*.feature".freeze
6
+
7
+ def initialize
8
+ super(FILE_PATTERN, split_configuration_path, "bundle exec cucumber")
9
+ end
10
+
11
+ def before_job
12
+ CucumberBoosterConfig::Injection.new(Dir.pwd, report_path).run
13
+ end
14
+
15
+ def after_job
16
+ TestBoosters::InsightsUploader.upload("cucumber", report_path)
17
+ end
18
+
19
+ def display_header
20
+ super
21
+
22
+ TestBoosters::ProjectInfo.display_ruby_version
23
+ TestBoosters::ProjectInfo.display_bundler_version
24
+ TestBoosters::ProjectInfo.display_cucumber_version
25
+ end
26
+
27
+ def report_path
28
+ @report_path ||= ENV["REPORT_PATH"] || "#{ENV["HOME"]}/cucumber_report.json"
29
+ end
30
+
31
+ def split_configuration_path
32
+ ENV["CUCUMBER_SPLIT_CONFIGURATION_PATH"] || "#{ENV["HOME"]}/cucumber_split_configuration.json"
33
+ end
34
+
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,17 @@
1
+ module TestBoosters
2
+ module Boosters
3
+ class ExUnit < Base
4
+
5
+ FILE_PATTERN = "test/**/*_test.exs".freeze
6
+
7
+ def initialize
8
+ super(FILE_PATTERN, split_configuration_path, "mix test")
9
+ end
10
+
11
+ def split_configuration_path
12
+ ENV["EX_UNIT_SPLIT_CONFIGURATION_PATH"] || "#{ENV["HOME"]}/ex_unit_split_configuration.json"
13
+ end
14
+
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,17 @@
1
+ module TestBoosters
2
+ module Boosters
3
+ class GoTest < Base
4
+
5
+ FILE_PATTERN = "**/*/*_test.go".freeze
6
+
7
+ def initialize
8
+ super(FILE_PATTERN, split_configuration_path, "go test")
9
+ end
10
+
11
+ def split_configuration_path
12
+ ENV["GO_TEST_SPLIT_CONFIGURATION_PATH"] || "#{ENV["HOME"]}/go_test_split_configuration.json"
13
+ end
14
+
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,21 @@
1
+ module TestBoosters
2
+ module Boosters
3
+ class Minitest < Base
4
+
5
+ FILE_PATTERN = "test/**/*_test.rb".freeze
6
+
7
+ def initialize
8
+ super(FILE_PATTERN, split_configuration_path, command)
9
+ end
10
+
11
+ def command
12
+ "ruby -e 'ARGV.each { |f| require \"./\#{f}\" }'"
13
+ end
14
+
15
+ def split_configuration_path
16
+ ENV["MINITEST_SPLIT_CONFIGURATION_PATH"] || "#{ENV["HOME"]}/minitest_split_configuration.json"
17
+ end
18
+
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,41 @@
1
+ module TestBoosters
2
+ module Boosters
3
+ class Rspec < Base
4
+
5
+ FILE_PATTERN = "spec/**/*_spec.rb".freeze
6
+
7
+ def initialize
8
+ super(FILE_PATTERN, split_configuration_path, command)
9
+ end
10
+
11
+ def display_header
12
+ super
13
+
14
+ TestBoosters::ProjectInfo.display_ruby_version
15
+ TestBoosters::ProjectInfo.display_bundler_version
16
+ TestBoosters::ProjectInfo.display_rspec_version
17
+ end
18
+
19
+ def after_job
20
+ TestBoosters::InsightsUploader.upload("rspec", report_path)
21
+ end
22
+
23
+ def command
24
+ @command ||= "bundle exec rspec #{rspec_options}"
25
+ end
26
+
27
+ def rspec_options
28
+ @rspec_options ||= "#{ENV["TB_RSPEC_OPTIONS"]} --format documentation --format json --out #{report_path}"
29
+ end
30
+
31
+ def report_path
32
+ @report_path ||= ENV["REPORT_PATH"] || "#{ENV["HOME"]}/rspec_report.json"
33
+ end
34
+
35
+ def split_configuration_path
36
+ ENV["RSPEC_SPLIT_CONFIGURATION_PATH"] || "#{ENV["HOME"]}/rspec_split_configuration.json"
37
+ end
38
+
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,45 @@
1
+ module TestBoosters
2
+ module Files
3
+
4
+ #
5
+ # Distributes test files based on split configuration, file pattern, and their file size
6
+ #
7
+ class Distributor
8
+
9
+ def initialize(split_configuration_path, file_pattern, job_count)
10
+ @split_configuration_path = split_configuration_path
11
+ @file_pattern = file_pattern
12
+ @job_count = job_count
13
+ end
14
+
15
+ def display_info
16
+ puts "Split configuration present: #{split_configuration.present? ? "yes" : "no"}"
17
+ puts "Split configuration valid: #{split_configuration.valid? ? "yes" : "no"}"
18
+ puts "Split configuration file count: #{split_configuration.all_files.size}"
19
+ end
20
+
21
+ def files_for(job_index)
22
+ known = all_files & split_configuration.files_for_job(job_index)
23
+ leftover = leftover_files.select(:index => job_index, :total => @job_count)
24
+
25
+ [known, leftover]
26
+ end
27
+
28
+ def all_files
29
+ @all_files ||= Dir[@file_pattern].sort
30
+ end
31
+
32
+ private
33
+
34
+ def leftover_files
35
+ @leftover_files ||= TestBoosters::Files::LeftoverFiles.new(all_files - split_configuration.all_files)
36
+ end
37
+
38
+ def split_configuration
39
+ @split_configuration ||= TestBoosters::Files::SplitConfiguration.new(@split_configuration_path)
40
+ end
41
+
42
+ end
43
+
44
+ end
45
+ end
@@ -0,0 +1,42 @@
1
+ module TestBoosters
2
+ module Files
3
+ class LeftoverFiles
4
+
5
+ attr_reader :files
6
+
7
+ def initialize(files)
8
+ @files = files
9
+ end
10
+
11
+ def select(options = {})
12
+ index = options.fetch(:index)
13
+ total = options.fetch(:total)
14
+
15
+ file_distribution(total)[index]
16
+ end
17
+
18
+ private
19
+
20
+ def file_distribution(job_count)
21
+ # create N empty boxes
22
+ jobs = Array.new(job_count) { [] }
23
+
24
+ # distribute files in Round Robin fashion
25
+ sorted_files_by_file_size.each.with_index do |file, index|
26
+ jobs[index % job_count] << file
27
+ end
28
+
29
+ jobs
30
+ end
31
+
32
+ def sorted_files_by_file_size
33
+ @sorted_files_by_file_size ||= existing_files.sort_by { |file| -File.size(file) }
34
+ end
35
+
36
+ def existing_files
37
+ @existing_files ||= @files.select { |file| File.file?(file) }
38
+ end
39
+
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,68 @@
1
+ module TestBoosters
2
+ module Files
3
+ class SplitConfiguration
4
+
5
+ Job = Struct.new(:files)
6
+
7
+ def initialize(path)
8
+ @path = path
9
+ @valid = true
10
+ end
11
+
12
+ def present?
13
+ File.exist?(@path)
14
+ end
15
+
16
+ def valid?
17
+ jobs # try to load data into memory
18
+
19
+ @valid
20
+ end
21
+
22
+ def all_files
23
+ @all_files ||= jobs.map(&:files).flatten.sort
24
+ end
25
+
26
+ def files_for_job(job_index)
27
+ job = jobs[job_index]
28
+
29
+ job ? job.files : []
30
+ end
31
+
32
+ def jobs
33
+ @jobs ||= present? ? load_data : []
34
+ end
35
+
36
+ private
37
+
38
+ # :reek:TooManyStatements
39
+ def load_data
40
+ @valid = false
41
+
42
+ content = JSON.parse(File.read(@path)).map do |raw_job|
43
+ files = raw_job.fetch("files").sort
44
+
45
+ TestBoosters::Files::SplitConfiguration::Job.new(files)
46
+ end
47
+
48
+ @valid = true
49
+
50
+ content
51
+ rescue TypeError, KeyError => ex
52
+ log_error("Split Configuration has invalid structure", ex)
53
+
54
+ []
55
+ rescue JSON::ParserError => ex
56
+ log_error("Split Configuration is not parsable", ex)
57
+
58
+ []
59
+ end
60
+
61
+ def log_error(message, exception)
62
+ TestBoosters::Logger.error(message)
63
+ TestBoosters::Logger.error(exception.inspect)
64
+ end
65
+
66
+ end
67
+ end
68
+ end
@@ -3,6 +3,8 @@ module TestBoosters
3
3
  module_function
4
4
 
5
5
  def upload(booster_type, file)
6
+ return unless File.exist?(file)
7
+
6
8
  cmd = "http POST '#{insights_url}' #{booster_type}:=@#{file}"
7
9
 
8
10
  TestBoosters::Shell.execute("#{cmd} > ~/insights_uploader.log", :silent => true)
@@ -0,0 +1,40 @@
1
+ module TestBoosters
2
+ class Job
3
+
4
+ def self.run(command, known_files, leftover_files)
5
+ new(command, known_files, leftover_files).run
6
+ end
7
+
8
+ def initialize(command, known_files, leftover_files)
9
+ @command = command
10
+ @known_files = known_files
11
+ @leftover_files = leftover_files
12
+ end
13
+
14
+ def display_header
15
+ puts
16
+ TestBoosters::Shell.display_files("Known files for this job", @known_files)
17
+ TestBoosters::Shell.display_files("Leftover files for this job", @leftover_files)
18
+
19
+ puts "=" * 80
20
+ puts ""
21
+ end
22
+
23
+ def files
24
+ @all_files ||= @known_files + @leftover_files
25
+ end
26
+
27
+ def run
28
+ display_header
29
+
30
+ if files.empty?
31
+ puts("No files to run in this job!")
32
+
33
+ return 0
34
+ end
35
+
36
+ TestBoosters::Shell.execute("#{@command} #{files.join(" ")}")
37
+ end
38
+
39
+ end
40
+ end
@@ -3,33 +3,31 @@ module TestBoosters
3
3
  module_function
4
4
 
5
5
  def display_ruby_version
6
- version = `ruby --version`.gsub("ruby ", "")
6
+ version = evaluate("ruby --version").gsub("ruby ", "")
7
7
 
8
8
  puts "Ruby Version: #{version}"
9
9
  end
10
10
 
11
11
  def display_bundler_version
12
- version = `bundle --version`.gsub("Bundler version ", "")
12
+ version = evaluate("bundle --version").gsub("Bundler version ", "")
13
13
 
14
14
  puts "Bundler Version: #{version}"
15
15
  end
16
16
 
17
17
  def display_rspec_version
18
- version = `bundle exec rspec --version`
18
+ version = evaluate("(bundle list | grep -q '* rspec') && bundle exec rspec --version || echo 'not found'")
19
19
 
20
20
  puts "RSpec Version: #{version}"
21
21
  end
22
22
 
23
23
  def display_cucumber_version
24
- version = `bundle exec cucumber --version`
24
+ version = evaluate("(bundle list | grep -q '* cucumber') && bundle exec cucumber --version || echo 'not found'")
25
25
 
26
26
  puts "Cucumber Version: #{version}"
27
27
  end
28
28
 
29
- def display_split_configuration_info(split_configuration)
30
- puts "Split configuration present: #{split_configuration.present? ? "yes" : "no"}"
31
- puts "Split configuration valid: #{split_configuration.valid? ? "yes" : "no"}"
32
- puts "Split configuration file count: #{split_configuration.all_files.size}"
29
+ def evaluate(command)
30
+ Bundler.with_clean_env { `#{command}` }
33
31
  end
34
32
 
35
33
  end
@@ -8,7 +8,9 @@ module TestBoosters
8
8
 
9
9
  puts command unless options[:silent] == true
10
10
 
11
- system(command)
11
+ Bundler.with_clean_env do
12
+ system(command)
13
+ end
12
14
 
13
15
  exit_status = $?.exitstatus
14
16
 
@@ -19,7 +21,7 @@ module TestBoosters
19
21
 
20
22
  def display_title(title)
21
23
  puts
22
- puts "========================= #{title} =========================="
24
+ puts "=== #{title} ===="
23
25
  puts
24
26
  end
25
27
 
@@ -1,3 +1,3 @@
1
1
  module TestBoosters
2
- VERSION = "1.8.0".freeze
2
+ VERSION = "2.0.0".freeze
3
3
  end
@@ -24,7 +24,6 @@ Gem::Specification.new do |spec|
24
24
  spec.add_development_dependency "rake", "~> 10.0"
25
25
  spec.add_development_dependency "rspec", "~> 3.5"
26
26
  spec.add_development_dependency "activesupport", "~> 4.0"
27
- spec.add_development_dependency "cucumber-rails", "~> 1.4.3"
28
27
 
29
28
  spec.add_development_dependency "rubocop", "~> 0.47.1"
30
29
  spec.add_development_dependency "rubocop-rspec", "~> 1.13.0"
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: semaphore_test_boosters
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.8.0
4
+ version: 2.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Developers at Rendered Text
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2017-03-25 00:00:00.000000000 Z
11
+ date: 2017-03-30 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: semaphore_cucumber_booster_config
@@ -66,20 +66,6 @@ dependencies:
66
66
  - - "~>"
67
67
  - !ruby/object:Gem::Version
68
68
  version: '4.0'
69
- - !ruby/object:Gem::Dependency
70
- name: cucumber-rails
71
- requirement: !ruby/object:Gem::Requirement
72
- requirements:
73
- - - "~>"
74
- - !ruby/object:Gem::Version
75
- version: 1.4.3
76
- type: :development
77
- prerelease: false
78
- version_requirements: !ruby/object:Gem::Requirement
79
- requirements:
80
- - - "~>"
81
- - !ruby/object:Gem::Version
82
- version: 1.4.3
83
69
  - !ruby/object:Gem::Dependency
84
70
  name: rubocop
85
71
  requirement: !ruby/object:Gem::Requirement
@@ -141,6 +127,9 @@ email:
141
127
  - devops@renderedtext.com
142
128
  executables:
143
129
  - cucumber_booster
130
+ - ex_unit_booster
131
+ - go_test_booster
132
+ - minitest_booster
144
133
  - rspec_booster
145
134
  extensions: []
146
135
  extra_rdoc_files: []
@@ -156,19 +145,26 @@ files:
156
145
  - bin/setup
157
146
  - config.reek
158
147
  - exe/cucumber_booster
148
+ - exe/ex_unit_booster
149
+ - exe/go_test_booster
150
+ - exe/minitest_booster
159
151
  - exe/rspec_booster
160
152
  - lib/test_boosters.rb
153
+ - lib/test_boosters/boosters/base.rb
154
+ - lib/test_boosters/boosters/cucumber.rb
155
+ - lib/test_boosters/boosters/ex_unit.rb
156
+ - lib/test_boosters/boosters/go_test.rb
157
+ - lib/test_boosters/boosters/minitest.rb
158
+ - lib/test_boosters/boosters/rspec.rb
161
159
  - lib/test_boosters/cli_parser.rb
162
- - lib/test_boosters/cucumber/booster.rb
163
- - lib/test_boosters/cucumber/job.rb
160
+ - lib/test_boosters/files/distributor.rb
161
+ - lib/test_boosters/files/leftover_files.rb
162
+ - lib/test_boosters/files/split_configuration.rb
164
163
  - lib/test_boosters/insights_uploader.rb
165
- - lib/test_boosters/leftover_files.rb
164
+ - lib/test_boosters/job.rb
166
165
  - lib/test_boosters/logger.rb
167
166
  - lib/test_boosters/project_info.rb
168
- - lib/test_boosters/rspec/booster.rb
169
- - lib/test_boosters/rspec/job.rb
170
167
  - lib/test_boosters/shell.rb
171
- - lib/test_boosters/split_configuration.rb
172
168
  - lib/test_boosters/version.rb
173
169
  - test_boosters.gemspec
174
170
  homepage: https://github.com/renderedtext/test-boosters
@@ -1,59 +0,0 @@
1
- module TestBoosters
2
- module Cucumber
3
- class Booster
4
-
5
- attr_reader :job_index
6
- attr_reader :job_count
7
-
8
- def initialize(job_index, job_count)
9
- @job_index = job_index
10
- @job_count = job_count
11
- end
12
-
13
- def run
14
- TestBoosters::Shell.display_title("Cucumber Booster v#{TestBoosters::VERSION}")
15
- display_system_info
16
-
17
- jobs[@job_index].run
18
- end
19
-
20
- def display_system_info
21
- TestBoosters::ProjectInfo.display_ruby_version
22
- TestBoosters::ProjectInfo.display_bundler_version
23
- TestBoosters::ProjectInfo.display_cucumber_version
24
- TestBoosters::ProjectInfo.display_split_configuration_info(split_configuration)
25
- puts
26
- end
27
-
28
- def jobs
29
- @jobs ||= Array.new(job_count) do |job_index|
30
- known = all_specs & split_configuration.files_for_job(job_index)
31
- leftover = leftover_specs.select(:index => job_index, :total => job_count)
32
-
33
- TestBoosters::Cucumber::Job.new(known, leftover)
34
- end
35
- end
36
-
37
- def all_specs
38
- @all_specs ||= Dir["#{specs_path}/**/*.feature"].sort
39
- end
40
-
41
- def leftover_specs
42
- @leftover_specs ||= TestBoosters::LeftoverFiles.new(all_specs - split_configuration.all_files)
43
- end
44
-
45
- def split_configuration
46
- @split_configuration ||= TestBoosters::SplitConfiguration.new(split_configuration_path)
47
- end
48
-
49
- def specs_path
50
- @specs_path ||= ENV["SPEC_PATH"] || "features"
51
- end
52
-
53
- def split_configuration_path
54
- ENV["CUCUMBER_SPLIT_CONFIGURATION_PATH"] || "#{ENV["HOME"]}/cucumber_split_configuration.json"
55
- end
56
-
57
- end
58
- end
59
- end
@@ -1,71 +0,0 @@
1
- module TestBoosters
2
- module Cucumber
3
- class Job
4
-
5
- attr_reader :files_from_split_configuration
6
- attr_reader :leftover_files
7
-
8
- def initialize(files_from_split_configuration, leftover_files)
9
- @files_from_split_configuration = files_from_split_configuration
10
- @leftover_files = leftover_files
11
- end
12
-
13
- # :reek:TooManyStatements { max_statements: 10 }
14
- def run
15
- if all_files.empty?
16
- puts("No files to run in this job!")
17
-
18
- return 0
19
- end
20
-
21
- run_cucumber_config
22
-
23
- display_job_info
24
-
25
- exit_status = run_cucumber
26
-
27
- upload_report
28
-
29
- exit_status
30
- end
31
-
32
- def display_job_info
33
- TestBoosters::Shell.display_files(
34
- "Known specs for this job",
35
- files_from_split_configuration)
36
-
37
- TestBoosters::Shell.display_files(
38
- "Leftover specs for this job",
39
- leftover_files)
40
- end
41
-
42
- def run_cucumber_config
43
- CucumberBoosterConfig::Injection.new(Dir.pwd, report_path).run
44
- puts "-------------------------------------------------------"
45
- puts
46
- end
47
-
48
- def run_cucumber
49
- TestBoosters::Shell.display_title("Running Cucumber")
50
- TestBoosters::Shell.execute(cucumber_command)
51
- end
52
-
53
- def upload_report
54
- TestBoosters::InsightsUploader.upload("cucumber", report_path)
55
- end
56
-
57
- def all_files
58
- @all_files ||= files_from_split_configuration + leftover_files
59
- end
60
-
61
- def cucumber_command
62
- "bundle exec cucumber #{all_files.join(" ")}"
63
- end
64
-
65
- def report_path
66
- @report_path ||= ENV["REPORT_PATH"] || "#{ENV["HOME"]}/cucumber_report.json"
67
- end
68
-
69
- end
70
- end
71
- end
@@ -1,40 +0,0 @@
1
- module TestBoosters
2
- class LeftoverFiles
3
-
4
- attr_reader :files
5
-
6
- def initialize(files)
7
- @files = files
8
- end
9
-
10
- def select(options = {})
11
- index = options.fetch(:index)
12
- total = options.fetch(:total)
13
-
14
- file_distribution(total)[index]
15
- end
16
-
17
- private
18
-
19
- def file_distribution(job_count)
20
- # create N empty boxes
21
- jobs = Array.new(job_count) { [] }
22
-
23
- # distribute files in Round Robin fashion
24
- sorted_files_by_file_size.each.with_index do |file, index|
25
- jobs[index % job_count] << file
26
- end
27
-
28
- jobs
29
- end
30
-
31
- def sorted_files_by_file_size
32
- @sorted_files_by_file_size ||= existing_files.sort_by { |file| -File.size(file) }
33
- end
34
-
35
- def existing_files
36
- @existing_files ||= @files.select { |file| File.file?(file) }
37
- end
38
-
39
- end
40
- end
@@ -1,59 +0,0 @@
1
- module TestBoosters
2
- module Rspec
3
- class Booster
4
-
5
- attr_reader :job_index
6
- attr_reader :job_count
7
-
8
- def initialize(job_index, job_count)
9
- @job_index = job_index
10
- @job_count = job_count
11
- end
12
-
13
- def run
14
- TestBoosters::Shell.display_title("RSpec Booster v#{TestBoosters::VERSION}")
15
- display_system_info
16
-
17
- jobs[@job_index].run
18
- end
19
-
20
- def display_system_info
21
- TestBoosters::ProjectInfo.display_ruby_version
22
- TestBoosters::ProjectInfo.display_bundler_version
23
- TestBoosters::ProjectInfo.display_rspec_version
24
- TestBoosters::ProjectInfo.display_split_configuration_info(split_configuration)
25
- puts
26
- end
27
-
28
- def jobs
29
- @jobs ||= Array.new(job_count) do |job_index|
30
- known = all_specs & split_configuration.files_for_job(job_index)
31
- leftover = leftover_specs.select(:index => job_index, :total => job_count)
32
-
33
- TestBoosters::Rspec::Job.new(known, leftover)
34
- end
35
- end
36
-
37
- def all_specs
38
- @all_specs ||= Dir["#{specs_path}/**/*_spec.rb"].sort
39
- end
40
-
41
- def leftover_specs
42
- @leftover_specs ||= TestBoosters::LeftoverFiles.new(all_specs - split_configuration.all_files)
43
- end
44
-
45
- def split_configuration
46
- @split_configuration ||= TestBoosters::SplitConfiguration.new(split_configuration_path)
47
- end
48
-
49
- def specs_path
50
- @specs_path ||= ENV["SPEC_PATH"] || "spec"
51
- end
52
-
53
- def split_configuration_path
54
- ENV["RSPEC_SPLIT_CONFIGURATION_PATH"] || "#{ENV["HOME"]}/rspec_split_configuration.json"
55
- end
56
-
57
- end
58
- end
59
- end
@@ -1,64 +0,0 @@
1
- module TestBoosters
2
- module Rspec
3
- class Job
4
-
5
- attr_reader :files_from_split_configuration
6
- attr_reader :leftover_files
7
-
8
- def initialize(files_from_split_configuration, leftover_files)
9
- @files_from_split_configuration = files_from_split_configuration
10
- @leftover_files = leftover_files
11
- end
12
-
13
- # :reek:TooManyStatements { max_statements: 10 }
14
- def run
15
- if all_files.empty?
16
- puts("No files to run in this job!")
17
-
18
- return 0
19
- end
20
-
21
- display_job_info
22
-
23
- exit_status = run_rspec
24
-
25
- upload_report
26
-
27
- exit_status
28
- end
29
-
30
- def display_job_info
31
- TestBoosters::Shell.display_files("Known specs for this job", files_from_split_configuration)
32
- TestBoosters::Shell.display_files("Leftover specs for this job", leftover_files)
33
-
34
- puts "RSpec options: #{rspec_options}"
35
- end
36
-
37
- def run_rspec
38
- TestBoosters::Shell.display_title("Running RSpec")
39
- TestBoosters::Shell.execute(rspec_command)
40
- end
41
-
42
- def upload_report
43
- TestBoosters::InsightsUploader.upload("rspec", report_path)
44
- end
45
-
46
- def all_files
47
- @all_files ||= files_from_split_configuration + leftover_files
48
- end
49
-
50
- def rspec_options
51
- "#{ENV["TB_RSPEC_OPTIONS"]} --format documentation --format json --out #{report_path}"
52
- end
53
-
54
- def rspec_command
55
- "bundle exec rspec #{rspec_options} #{all_files.join(" ")}"
56
- end
57
-
58
- def report_path
59
- @report_path ||= ENV["REPORT_PATH"] || "#{ENV["HOME"]}/rspec_report.json"
60
- end
61
-
62
- end
63
- end
64
- end
@@ -1,66 +0,0 @@
1
- module TestBoosters
2
- class SplitConfiguration
3
-
4
- Job = Struct.new(:files)
5
-
6
- def initialize(path)
7
- @path = path
8
- @valid = true
9
- end
10
-
11
- def present?
12
- File.exist?(@path)
13
- end
14
-
15
- def valid?
16
- jobs # try to load data into memory
17
-
18
- @valid
19
- end
20
-
21
- def all_files
22
- @all_files ||= jobs.map(&:files).flatten.sort
23
- end
24
-
25
- def files_for_job(job_index)
26
- job = jobs[job_index]
27
-
28
- job ? job.files : []
29
- end
30
-
31
- def jobs
32
- @jobs ||= present? ? load_data : []
33
- end
34
-
35
- private
36
-
37
- # :reek:TooManyStatements
38
- def load_data
39
- @valid = false
40
-
41
- content = JSON.parse(File.read(@path)).map do |raw_job|
42
- files = raw_job.fetch("files").sort
43
-
44
- TestBoosters::SplitConfiguration::Job.new(files)
45
- end
46
-
47
- @valid = true
48
-
49
- content
50
- rescue TypeError, KeyError => ex
51
- log_error("Split Configuration has invalid structure", ex)
52
-
53
- []
54
- rescue JSON::ParserError => ex
55
- log_error("Split Configuration is not parsable", ex)
56
-
57
- []
58
- end
59
-
60
- def log_error(message, exception)
61
- TestBoosters::Logger.error(message)
62
- TestBoosters::Logger.error(exception.inspect)
63
- end
64
-
65
- end
66
- end