parallel_tests 2.32.0 → 3.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
  SHA256:
3
- metadata.gz: f9f48375f06f2320fdda57c5c1340b8aedf1761541d4c802c5a17b6f21cbf858
4
- data.tar.gz: 8e91a9f26aa2710aa023b6d779d7fdf0e768213262d75b7d9969751a3e825089
3
+ metadata.gz: 0c8f92fb8fb19ff4348080358222c4984bcc5721ddd4779433ad4b8beead46a0
4
+ data.tar.gz: e3fb4beed5a5391401e8fcd729a5308c274ac2ddc61b3cd548e655a25009ba5d
5
5
  SHA512:
6
- metadata.gz: 6468e8bbb055db1eaee1a8512cb4226ceeb7acc2ba880d8be30117d863f8b870629088835d2628d28981e9b193a40239646d8a4de8e61467bd0bc48fae50e92e
7
- data.tar.gz: 0dcd9f3aee1aead8329b76e770eb814ef62f465803629fe236d764b6a874eb827458b008aea240689ecadafa02388d49e71291d2c3cca5e74bc24d66137960ce
6
+ metadata.gz: bff5dfd53ba1acc4bb654d17f49d9d9deb1c86eff894232fc698dd3100fd2fbb7dd15ad11c1ebdc501438003ce62b2f65a7befcbc970e15d2b3e340f47ebf928
7
+ data.tar.gz: a5ded77e36a14a8bebea03777666e6de95f787edaf79dcf27b8d99d91c69b4779cb43e5ba5daf13f7940b2b262ad49eede907e8c9482749e30e2b272cf965245
@@ -316,9 +316,8 @@ module ParallelTests
316
316
  end
317
317
 
318
318
  def final_fail_message
319
- fail_message = "#{@runner.name}s Failed"
319
+ fail_message = "Tests Failed"
320
320
  fail_message = "\e[31m#{fail_message}\e[0m" if use_colors?
321
-
322
321
  fail_message
323
322
  end
324
323
 
@@ -0,0 +1,31 @@
1
+ begin
2
+ gem "cuke_modeler", "~> 3.0"
3
+ require 'cuke_modeler'
4
+ rescue LoadError
5
+ raise 'Grouping by number of cucumber steps requires the `cuke_modeler` modeler gem with requirement `~> 3.0`. Add `gem "cuke_modeler", "~> 3.0"` to your `Gemfile`, run `bundle install` and try again.'
6
+ end
7
+
8
+ module ParallelTests
9
+ module Cucumber
10
+ class FeaturesWithSteps
11
+ class << self
12
+ def all(tests, options)
13
+ ignore_tag_pattern = options[:ignore_tag_pattern].nil? ? nil : Regexp.compile(options[:ignore_tag_pattern])
14
+ # format of hash will be FILENAME => NUM_STEPS
15
+ steps_per_file = tests.each_with_object({}) do |file,steps|
16
+ feature = ::CukeModeler::FeatureFile.new(file).feature
17
+
18
+ # skip feature if it matches tag regex
19
+ next if feature.tags.grep(ignore_tag_pattern).any?
20
+
21
+ # count the number of steps in the file
22
+ # will only include a feature if the regex does not match
23
+ all_steps = feature.scenarios.map{|a| a.steps.count if a.tags.grep(ignore_tag_pattern).empty? }.compact
24
+ steps[file] = all_steps.inject(0,:+)
25
+ end
26
+ steps_per_file.sort_by { |_, value| -value }
27
+ end
28
+ end
29
+ end
30
+ end
31
+ end
@@ -1,37 +1,33 @@
1
- require 'cucumber/tag_expressions/parser'
2
- require 'cucumber/core/gherkin/tag_expression'
3
-
4
1
  module ParallelTests
5
2
  module Cucumber
6
3
  module Formatters
7
4
  class ScenarioLineLogger
8
5
  attr_reader :scenarios
9
6
 
10
- def initialize(tag_expression = ::Cucumber::Core::Gherkin::TagExpression.new([]))
7
+ def initialize(tag_expression = nil)
11
8
  @scenarios = []
12
9
  @tag_expression = tag_expression
13
10
  end
14
11
 
15
12
  def visit_feature_element(uri, feature_element, feature_tags, line_numbers: [])
16
- scenario_tags = feature_element[:tags].map { |tag| tag[:name] }
13
+ scenario_tags = feature_element.tags.map { |tag| tag.name }
17
14
  scenario_tags = feature_tags + scenario_tags
18
- if feature_element[:examples].nil? # :Scenario
19
- test_line = feature_element[:location][:line]
15
+ if feature_element.is_a?(CukeModeler::Scenario) # :Scenario
16
+ test_line = feature_element.source_line
20
17
 
21
18
  # We don't accept the feature_element if the current tags are not valid
22
- return unless @tag_expression.evaluate(scenario_tags)
19
+ return unless matches_tags?(scenario_tags)
23
20
  # or if it is not at the correct location
24
21
  return if line_numbers.any? && !line_numbers.include?(test_line)
25
22
 
26
- @scenarios << [uri, feature_element[:location][:line]].join(":")
23
+ @scenarios << [uri, feature_element.source_line].join(":")
27
24
  else # :ScenarioOutline
28
- feature_element[:examples].each do |example|
29
- example_tags = example[:tags].map { |tag| tag[:name] }
25
+ feature_element.examples.each do |example|
26
+ example_tags = example.tags.map(&:name)
30
27
  example_tags = scenario_tags + example_tags
31
- next unless @tag_expression.evaluate(example_tags)
32
- rows = example[:tableBody].select { |body| body[:type] == :TableRow }
33
- rows.each do |row|
34
- test_line = row[:location][:line]
28
+ next unless matches_tags?(example_tags)
29
+ example.rows[1..-1].each do |row|
30
+ test_line = row.source_line
35
31
  next if line_numbers.any? && !line_numbers.include?(test_line)
36
32
 
37
33
  @scenarios << [uri, test_line].join(':')
@@ -42,6 +38,12 @@ module ParallelTests
42
38
 
43
39
  def method_missing(*args)
44
40
  end
41
+
42
+ private
43
+
44
+ def matches_tags?(tags)
45
+ @tag_expression.nil? || @tag_expression.evaluate(tags)
46
+ end
45
47
  end
46
48
  end
47
49
  end
@@ -1,12 +1,17 @@
1
1
  require 'cucumber/tag_expressions/parser'
2
- require 'cucumber/core/gherkin/tag_expression'
3
2
  require 'cucumber/runtime'
4
3
  require 'cucumber'
5
4
  require 'parallel_tests/cucumber/scenario_line_logger'
6
5
  require 'parallel_tests/gherkin/listener'
7
- require 'gherkin/errors'
8
6
  require 'shellwords'
9
7
 
8
+ begin
9
+ gem "cuke_modeler", "~> 3.0"
10
+ require 'cuke_modeler'
11
+ rescue LoadError
12
+ raise 'Grouping by individual cucumber scenarios requires the `cuke_modeler` modeler gem with requirement `~> 3.0`. Add `gem "cuke_modeler", "~> 3.0"` to your `Gemfile`, run `bundle install` and try again.'
13
+ end
14
+
10
15
  module ParallelTests
11
16
  module Cucumber
12
17
  class Scenarios
@@ -40,32 +45,17 @@ module ParallelTests
40
45
  path, *test_lines = path.split(/:(?=\d+)/)
41
46
  test_lines.map!(&:to_i)
42
47
 
43
- # We encode the file and get the content of it
44
- source = ::Cucumber::Runtime::NormalisedEncodingFile.read(path)
45
48
  # We create a Gherkin document, this will be used to decode the details of each scenario
46
- document = ::Cucumber::Core::Gherkin::Document.new(path, source)
47
-
48
- # We create a parser for the gherkin document
49
- parser = ::Gherkin::Parser.new()
50
- scanner = ::Gherkin::TokenScanner.new(document.body)
51
-
52
- begin
53
- # We make an attempt to parse the gherkin document, this could be failed if the document is not well formatted
54
- result = parser.parse(scanner)
55
- feature_tags = result[:feature][:tags].map { |tag| tag[:name] }
56
-
57
- # We loop on each children of the feature
58
- result[:feature][:children].each do |feature_element|
59
- # If the type of the child is not a scenario or scenario outline, we continue, we are only interested by the name of the scenario here
60
- next unless /Scenario/.match(feature_element[:type])
49
+ document = ::CukeModeler::FeatureFile.new(path)
50
+ feature = document.feature
61
51
 
62
- # It's a scenario, we add it to the scenario_line_logger
63
- scenario_line_logger.visit_feature_element(document.uri, feature_element, feature_tags, line_numbers: test_lines)
64
- end
52
+ # We make an attempt to parse the gherkin document, this could be failed if the document is not well formatted
53
+ feature_tags = feature.tags.map(&:name)
65
54
 
66
- rescue StandardError => e
67
- # Exception if the document is no well formated or error in the tags
68
- raise ::Cucumber::Core::Gherkin::ParseError.new("#{document.uri}: #{e.message}")
55
+ # We loop on each children of the feature
56
+ feature.tests.each do |test|
57
+ # It's a scenario, we add it to the scenario_line_logger
58
+ scenario_line_logger.visit_feature_element(document.path, test, feature_tags, line_numbers: test_lines)
69
59
  end
70
60
  end
71
61
 
@@ -1,5 +1,3 @@
1
- require 'gherkin/parser'
2
-
3
1
  module ParallelTests
4
2
  module Gherkin
5
3
  class Listener
@@ -14,7 +14,7 @@ module ParallelTests
14
14
  end
15
15
 
16
16
  config.on_event :test_case_finished do |event|
17
- @example_times[event.test_case.feature.file] += ParallelTests.now.to_f - @start_at
17
+ @example_times[event.test_case.location.file] += ParallelTests.now.to_f - @start_at
18
18
  end
19
19
 
20
20
  config.on_event :test_run_finished do |_|
@@ -2,7 +2,7 @@ module ParallelTests
2
2
  class Grouper
3
3
  class << self
4
4
  def by_steps(tests, num_groups, options)
5
- features_with_steps = build_features_with_steps(tests, options)
5
+ features_with_steps = group_by_features_with_steps(tests, options)
6
6
  in_even_groups_by_size(features_with_steps, num_groups)
7
7
  end
8
8
 
@@ -41,23 +41,9 @@ module ParallelTests
41
41
  group[:size] += size
42
42
  end
43
43
 
44
- def build_features_with_steps(tests, options)
45
- require 'gherkin/parser'
46
- ignore_tag_pattern = options[:ignore_tag_pattern].nil? ? nil : Regexp.compile(options[:ignore_tag_pattern])
47
- parser = ::Gherkin::Parser.new
48
- # format of hash will be FILENAME => NUM_STEPS
49
- steps_per_file = tests.each_with_object({}) do |file,steps|
50
- feature = parser.parse(File.read(file)).fetch(:feature)
51
-
52
- # skip feature if it matches tag regex
53
- next if feature[:tags].grep(ignore_tag_pattern).any?
54
-
55
- # count the number of steps in the file
56
- # will only include a feature if the regex does not match
57
- all_steps = feature[:children].map{|a| a[:steps].count if a[:tags].grep(ignore_tag_pattern).empty? }.compact
58
- steps[file] = all_steps.inject(0,:+)
59
- end
60
- steps_per_file.sort_by { |_, value| -value }
44
+ def group_by_features_with_steps(tests, options)
45
+ require 'parallel_tests/cucumber/features_with_steps'
46
+ ParallelTests::Cucumber::FeaturesWithSteps.all(tests, options)
61
47
  end
62
48
 
63
49
  def group_by_scenarios(tests, options={})
@@ -4,8 +4,6 @@ module ParallelTests
4
4
  module RSpec
5
5
  class Runner < ParallelTests::Test::Runner
6
6
  DEV_NULL = (WINDOWS ? "NUL" : "/dev/null")
7
- NAME = 'RSpec'
8
-
9
7
  class << self
10
8
  def run_tests(test_files, process_number, num_processes, options)
11
9
  exe = executable # expensive, so we cache
@@ -3,15 +3,9 @@ require 'parallel_tests'
3
3
  module ParallelTests
4
4
  module Test
5
5
  class Runner
6
- NAME = 'Test'
7
-
8
6
  class << self
9
7
  # --- usually overwritten by other runners
10
8
 
11
- def name
12
- NAME
13
- end
14
-
15
9
  def runtime_log
16
10
  'tmp/parallel_runtime_test.log'
17
11
  end
@@ -1,3 +1,3 @@
1
1
  module ParallelTests
2
- VERSION = Version = '2.32.0'
2
+ VERSION = Version = '3.0.0'
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: parallel_tests
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.32.0
4
+ version: 3.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Michael Grosser
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-03-15 00:00:00.000000000 Z
11
+ date: 2020-06-10 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: parallel
@@ -42,6 +42,7 @@ files:
42
42
  - lib/parallel_tests.rb
43
43
  - lib/parallel_tests/cli.rb
44
44
  - lib/parallel_tests/cucumber/failures_logger.rb
45
+ - lib/parallel_tests/cucumber/features_with_steps.rb
45
46
  - lib/parallel_tests/cucumber/runner.rb
46
47
  - lib/parallel_tests/cucumber/scenario_line_logger.rb
47
48
  - lib/parallel_tests/cucumber/scenarios.rb
@@ -67,8 +68,8 @@ licenses:
67
68
  - MIT
68
69
  metadata:
69
70
  bug_tracker_uri: https://github.com/grosser/parallel_tests/issues
70
- documentation_uri: https://github.com/grosser/parallel_tests/blob/v2.32.0/Readme.md
71
- source_code_uri: https://github.com/grosser/parallel_tests/tree/v2.32.0
71
+ documentation_uri: https://github.com/grosser/parallel_tests/blob/v3.0.0/Readme.md
72
+ source_code_uri: https://github.com/grosser/parallel_tests/tree/v3.0.0
72
73
  wiki_uri: https://github.com/grosser/parallel_tests/wiki
73
74
  post_install_message:
74
75
  rdoc_options: []
@@ -78,14 +79,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
78
79
  requirements:
79
80
  - - ">="
80
81
  - !ruby/object:Gem::Version
81
- version: 2.2.0
82
+ version: 2.4.0
82
83
  required_rubygems_version: !ruby/object:Gem::Requirement
83
84
  requirements:
84
85
  - - ">="
85
86
  - !ruby/object:Gem::Version
86
87
  version: '0'
87
88
  requirements: []
88
- rubygems_version: 3.0.3
89
+ rubygems_version: 3.1.3
89
90
  signing_key:
90
91
  specification_version: 4
91
92
  summary: Run Test::Unit / RSpec / Cucumber / Spinach in parallel