parallel_tests 2.32.0 → 3.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
  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