semaphore_test_boosters 1.8.0 → 2.0.0

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 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