parallel_tests 0.16.3 → 0.16.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 483fe80b7a68cc0f89853183082d652d9a0d4592
4
- data.tar.gz: 233b2a01c1f68b53e00a8e0b60c2a728c62aa98c
3
+ metadata.gz: b1e3fb69bc5868e4a5321edbbc4f4527aaa7d277
4
+ data.tar.gz: f6dc34a502ef7a65f565ecff44bf0990154d2ed3
5
5
  SHA512:
6
- metadata.gz: d546de76b8543b631efbac1feec87a799e025c7f38685b101d5e7ed9cde3d71ec17d13fd0649f35f7a82df35a2af0bb1376cc16ed8e5e128aab792358345900b
7
- data.tar.gz: 0e71947a9e6a4f0fde5a44fa873bcdb5dadc577bdad83eed429ea526043c99332ab7de9b26e0d0bac63660b359a54d45305e46dd49b229aa55ad31d6c53e41dc
6
+ metadata.gz: 92e953b15c06a785571f9c1aafc3fcdfb4ae6adf03cd9810215079485a9780a6cc280e2052aa857ee211697930c3b0530f1c1366ac5e560052a87c7f6ab008e8
7
+ data.tar.gz: df03a89e62a972b117a4e8b2ac9be3ebdd296ae6031c9ff8b392d8743a95ee96eb06e001e2da41b00e58cc2d7b6c1f53367fe41ce359840fefe2d450d18ea0ee
data/Gemfile.lock CHANGED
@@ -1,29 +1,29 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- parallel_tests (0.16.3)
4
+ parallel_tests (0.16.4)
5
5
  parallel
6
6
 
7
7
  GEM
8
8
  remote: https://rubygems.org/
9
9
  specs:
10
- builder (3.0.0)
10
+ builder (3.2.2)
11
11
  bump (0.3.8)
12
12
  colorize (0.5.8)
13
- cucumber (1.1.4)
13
+ cucumber (1.3.10)
14
14
  builder (>= 2.1.2)
15
- diff-lcs (>= 1.1.2)
16
- gherkin (~> 2.7.1)
17
- json (>= 1.4.6)
18
- term-ansicolor (>= 1.0.6)
19
- diff-lcs (1.2.4)
20
- gherkin (2.7.6)
21
- json (>= 1.4.6)
22
- gherkin (2.7.6-java)
23
- json (>= 1.4.6)
15
+ diff-lcs (>= 1.1.3)
16
+ gherkin (~> 2.12)
17
+ multi_json (>= 1.7.5, < 2.0)
18
+ multi_test (>= 0.0.2)
19
+ diff-lcs (1.2.5)
20
+ gherkin (2.12.2)
21
+ multi_json (~> 1.3)
22
+ gherkin (2.12.2-java)
23
+ multi_json (~> 1.3)
24
24
  gherkin-ruby (0.3.0)
25
- json (1.7.5)
26
- json (1.7.5-java)
25
+ multi_json (1.8.2)
26
+ multi_test (0.0.2)
27
27
  parallel (0.9.0)
28
28
  rake (10.0.3)
29
29
  rspec (2.13.0)
@@ -37,7 +37,6 @@ GEM
37
37
  spinach (0.8.3)
38
38
  colorize (= 0.5.8)
39
39
  gherkin-ruby (~> 0.3.0)
40
- term-ansicolor (1.0.7)
41
40
  test-unit (2.4.4)
42
41
 
43
42
  PLATFORMS
data/Readme.md CHANGED
@@ -213,7 +213,7 @@ TIPS
213
213
  - [RSpec] Instantly see failures (instead of just a red F) with [rspec-instafail](https://github.com/grosser/rspec-instafail)
214
214
  - [Bundler] if you have a `Gemfile` then `bundle exec` will be used to run tests
215
215
  - [Cucumber] add a `parallel: foo` profile to your `config/cucumber.yml` and it will be used to run parallel tests
216
- - [Cucumber] Pass in cucumber options by not giving the options an identifier ex: parallel:features[x,y,'cucumber_opts']
216
+ - [Cucumber] Pass in cucumber options by not giving the options an identifier ex: `rake parallel:features[,,'cucumber_opts']`
217
217
  - [Capybara setup](https://github.com/grosser/parallel_tests/wiki)
218
218
  - [Sphinx setup](https://github.com/grosser/parallel_tests/wiki)
219
219
  - [Capistrano setup](https://github.com/grosser/parallel_tests/wiki/Remotely-with-capistrano) let your tests run on a big box instead of your laptop
@@ -97,6 +97,7 @@ BANNER
97
97
  group tests by:
98
98
  found - order of finding files
99
99
  steps - number of cucumber/spinach steps
100
+ scenarios - individual cucumber scenarios
100
101
  default - runtime or filesize
101
102
  TEXT
102
103
  ) { |type| options[:group_by] = type.to_sym }
@@ -0,0 +1,51 @@
1
+ require 'gherkin/tag_expression'
2
+
3
+ module ParallelTests
4
+ module Cucumber
5
+ module Formatters
6
+ class ScenarioLineLogger
7
+ attr_reader :scenarios
8
+
9
+ def initialize(tag_expression = ::Gherkin::TagExpression.new([]))
10
+ @scenarios = []
11
+ @tag_expression = tag_expression
12
+ end
13
+
14
+ def visit_feature_element(feature_element)
15
+ return unless @tag_expression.evaluate(feature_element.source_tags)
16
+
17
+ case feature_element
18
+ when ::Cucumber::Ast::Scenario
19
+ line = if feature_element.respond_to?(:line)
20
+ feature_element.line
21
+ else
22
+ feature_element.instance_variable_get(:@line)
23
+ end
24
+ @scenarios << [feature_element.feature.file, line].join(":")
25
+ when ::Cucumber::Ast::ScenarioOutline
26
+ sections = feature_element.instance_variable_get(:@example_sections)
27
+ sections.each { |section|
28
+ rows = if section[1].respond_to?(:rows)
29
+ section[1].rows
30
+ else
31
+ section[1].instance_variable_get(:@rows)
32
+ end
33
+ rows.each_with_index { |row, index|
34
+ next if index == 0 # slices didn't work with jruby data structure
35
+ line = if row.respond_to?(:line)
36
+ row.line
37
+ else
38
+ row.instance_variable_get(:@line)
39
+ end
40
+ @scenarios << [feature_element.feature.file, line].join(":")
41
+ }
42
+ }
43
+ end
44
+ end
45
+
46
+ def method_missing(*args)
47
+ end
48
+ end
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,36 @@
1
+ require 'gherkin/tag_expression'
2
+ require 'cucumber/runtime'
3
+ require 'cucumber'
4
+ require 'parallel_tests/cucumber/scenario_line_logger'
5
+ require 'parallel_tests/gherkin/listener'
6
+
7
+ module ParallelTests
8
+ module Cucumber
9
+ class Scenarios
10
+ class << self
11
+ def all(files, options={})
12
+ tag_expressions = if options[:ignore_tag_pattern]
13
+ options[:ignore_tag_pattern].split(/\s*,\s*/).map {|tag| "~#{tag}" }
14
+ else
15
+ []
16
+ end
17
+ split_into_scenarios files, tag_expressions
18
+ end
19
+
20
+ private
21
+
22
+ def split_into_scenarios(files, tags=[])
23
+ tag_expression = ::Gherkin::TagExpression.new(tags)
24
+ scenario_line_logger = ParallelTests::Cucumber::Formatters::ScenarioLineLogger.new(tag_expression)
25
+ loader = ::Cucumber::Runtime::FeaturesLoader.new(files, [], tag_expression)
26
+
27
+ loader.features.each do |feature|
28
+ feature.accept(scenario_line_logger)
29
+ end
30
+
31
+ scenario_line_logger.scenarios
32
+ end
33
+ end
34
+ end
35
+ end
36
+ end
@@ -19,7 +19,7 @@ module ParallelTests
19
19
  end
20
20
 
21
21
  def test_file_name
22
- "feature"
22
+ @test_file_name || "feature"
23
23
  end
24
24
 
25
25
  def test_suffix
@@ -37,7 +37,7 @@ module ParallelTests
37
37
  sort_order = %w[scenario step failed undefined skipped pending passed]
38
38
 
39
39
  %w[scenario step].map do |group|
40
- group_results = results.grep /^\d+ #{group}/
40
+ group_results = results.grep(/^\d+ #{group}/)
41
41
  next if group_results.empty?
42
42
 
43
43
  sums = sum_up_results(group_results)
@@ -67,8 +67,12 @@ module ParallelTests
67
67
  end
68
68
 
69
69
  def tests_in_groups(tests, num_groups, options={})
70
- if options[:group_by] == :steps
71
- Grouper.by_steps(find_tests(tests, options), num_groups, options)
70
+ if options[:group_by] == :scenarios
71
+ @test_file_name = "scenario"
72
+ end
73
+ method = "by_#{options[:group_by]}"
74
+ if Grouper.respond_to?(method)
75
+ Grouper.send(method, find_tests(tests, options), num_groups, options)
72
76
  else
73
77
  super
74
78
  end
@@ -85,14 +89,14 @@ module ParallelTests
85
89
 
86
90
  def determine_executable
87
91
  case
88
- when File.exists?("bin/#{name}")
89
- "bin/#{name}"
90
- when ParallelTests.bundler_enabled?
91
- "bundle exec #{name}"
92
- when File.file?("script/#{name}")
93
- "script/#{name}"
94
- else
95
- "#{name}"
92
+ when File.exists?("bin/#{name}")
93
+ "bin/#{name}"
94
+ when ParallelTests.bundler_enabled?
95
+ "bundle exec #{name}"
96
+ when File.file?("script/#{name}")
97
+ "script/#{name}"
98
+ else
99
+ "#{name}"
96
100
  end
97
101
  end
98
102
 
@@ -1,3 +1,5 @@
1
+ require 'parallel_tests/cucumber/scenarios'
2
+
1
3
  module ParallelTests
2
4
  class Grouper
3
5
  class << self
@@ -6,22 +8,22 @@ module ParallelTests
6
8
  in_even_groups_by_size(features_with_steps, num_groups)
7
9
  end
8
10
 
9
- def in_even_groups_by_size(items_with_sizes, num_groups, options = {})
11
+ def by_scenarios(tests, num_groups, options={})
12
+ scenarios = group_by_scenarios(tests, options)
13
+ in_even_groups_by_size(scenarios, num_groups)
14
+ end
15
+
16
+ def in_even_groups_by_size(items, num_groups, options= {})
10
17
  groups = Array.new(num_groups) { {:items => [], :size => 0} }
11
18
 
12
19
  # add all files that should run in a single process to one group
13
20
  (options[:single_process] || []).each do |pattern|
14
- matched, items_with_sizes = items_with_sizes.partition { |item, size| item =~ pattern }
21
+ matched, items = items.partition { |item, size| item =~ pattern }
15
22
  matched.each { |item, size| add_to_group(groups.first, item, size) }
16
23
  end
17
24
 
18
25
  groups_to_fill = (options[:isolate] ? groups[1..-1] : groups)
19
-
20
- # add all other files
21
- largest_first(items_with_sizes).each do |item, size|
22
- smallest = smallest_group(groups_to_fill)
23
- add_to_group(smallest, item, size)
24
- end
26
+ group_features_by_size(items_to_group(items), groups_to_fill)
25
27
 
26
28
  groups.map!{|g| g[:items].sort }
27
29
  end
@@ -51,6 +53,22 @@ module ParallelTests
51
53
  }
52
54
  listener.collect.sort_by{|_,value| -value }
53
55
  end
56
+
57
+ def group_by_scenarios(tests, options={})
58
+ ParallelTests::Cucumber::Scenarios.all(tests, options)
59
+ end
60
+
61
+ def group_features_by_size(items, groups_to_fill)
62
+ items.each do |item, size|
63
+ size ||= 1
64
+ smallest = smallest_group(groups_to_fill)
65
+ add_to_group(smallest, item, size)
66
+ end
67
+ end
68
+
69
+ def items_to_group(items)
70
+ items.first && items.first.size == 2 ? largest_first(items) : items
71
+ end
54
72
  end
55
73
  end
56
74
  end
@@ -1,3 +1,3 @@
1
1
  module ParallelTests
2
- VERSION = Version = '0.16.3'
2
+ VERSION = Version = '0.16.4'
3
3
  end
@@ -304,6 +304,36 @@ cucumber features/fail1.feature:2 # Scenario: xxx
304
304
  3 steps (2 failed, 1 passed)
305
305
  """
306
306
  end
307
+
308
+ it "groups by scenario" do
309
+ write "features/long.feature", <<-EOS
310
+ Feature: xxx
311
+ Scenario: xxx
312
+ Given I print TEST_ENV_NUMBER
313
+
314
+ Scenario: xxx
315
+ Given I print TEST_ENV_NUMBER
316
+
317
+ Scenario Outline: xxx
318
+ Given I print TEST_ENV_NUMBER
319
+
320
+ Examples:
321
+ | num |
322
+ | one |
323
+ | two |
324
+ EOS
325
+ result = run_tests "features", :type => "cucumber", :add => "--group-by scenarios"
326
+ result.should include("2 processes for 4 scenarios")
327
+ end
328
+
329
+ it "groups by step" do
330
+ write "features/good1.feature", "Feature: xxx\n Scenario: xxx\n Given I print TEST_ENV_NUMBER"
331
+ write "features/good2.feature", "Feature: xxx\n Scenario: xxx\n Given I print TEST_ENV_NUMBER"
332
+
333
+ result = run_tests "features", :type => "cucumber", :add => '--group-by steps'
334
+
335
+ result.should include("2 processes for 2 features")
336
+ end
307
337
  end
308
338
 
309
339
  context "Spinach", :fails_on_ruby_187 => true do
@@ -0,0 +1,59 @@
1
+ require 'tempfile'
2
+ require 'parallel_tests/cucumber/scenarios'
3
+
4
+ module ParallelTests
5
+ module Cucumber
6
+ describe Scenarios do
7
+ describe '.all' do
8
+ context 'by default' do
9
+ let(:feature_file) do
10
+ Tempfile.new('grouper.feature').tap do |feature|
11
+ feature.write <<-EOS
12
+ Feature: Grouping by scenario
13
+
14
+ Scenario: First
15
+ Given I do nothing
16
+
17
+ Scenario: Second
18
+ Given I don't do anything
19
+ EOS
20
+ feature.rewind
21
+ end
22
+ end
23
+
24
+ it 'returns all the scenarios' do
25
+ scenarios = Scenarios.all([feature_file.path])
26
+ scenarios.should eq %W(#{feature_file.path}:3 #{feature_file.path}:6)
27
+ end
28
+ end
29
+
30
+ context 'with tags' do
31
+ let(:feature_file) do
32
+ Tempfile.new('grouper.feature').tap do |feature|
33
+ feature.write <<-EOS
34
+ Feature: Grouping by scenario
35
+
36
+ @wip
37
+ Scenario: First
38
+ Given I do nothing
39
+
40
+ Scenario: Second
41
+ Given I don't do anything
42
+
43
+ @ignore
44
+ Scenario: Third
45
+ Given I am ignored
46
+ EOS
47
+ feature.rewind
48
+ end
49
+ end
50
+
51
+ it 'ignores those scenarios' do
52
+ scenarios = Scenarios.all([feature_file.path], :ignore_tag_pattern => '@ignore, @wip')
53
+ scenarios.should eq %W(#{feature_file.path}:7)
54
+ end
55
+ end
56
+ end
57
+ end
58
+ end
59
+ end
@@ -49,4 +49,13 @@ describe ParallelTests::Grouper do
49
49
  call(6).should == [["5"], ["4"], ["3"], ["2"], ["1"], []]
50
50
  end
51
51
  end
52
+
53
+ describe :by_scenarios do
54
+ let(:feature_file) { double 'file' }
55
+
56
+ it 'splits a feature into individual scenarios' do
57
+ ParallelTests::Cucumber::Scenarios.should_receive(:all).and_return({ 'feature_file:3' => 1 })
58
+ ParallelTests::Grouper.by_scenarios([feature_file], 1)
59
+ end
60
+ end
52
61
  end
@@ -22,6 +22,15 @@ describe ParallelTests::Tasks do
22
22
  args = {:count => 2, :pattern => "plain", :options => "-p default"}
23
23
  ParallelTests::Tasks.parse_args(args).should == [2, "plain", "-p default"]
24
24
  end
25
+
26
+ it "should return the count, pattern, and options" do
27
+ args = {
28
+ :count => 2,
29
+ :pattern => "plain",
30
+ :options => "-p default --group-by steps",
31
+ }
32
+ ParallelTests::Tasks.parse_args(args).should == [2, "plain", "-p default --group-by steps"]
33
+ end
25
34
  end
26
35
 
27
36
  describe ".rails_env" do
@@ -43,7 +43,7 @@ describe ParallelTests::Test::Runner do
43
43
 
44
44
  it "does sort when not passed do_sort option" do
45
45
  ParallelTests::Test::Runner.stub!(:tests_with_runtime).and_return([])
46
- ParallelTests::Grouper.should_receive(:largest_first).and_return([])
46
+ ParallelTests::Grouper.should_receive(:group_features_by_size).and_return([])
47
47
  call([], 1)
48
48
  end
49
49
 
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: 0.16.3
4
+ version: 0.16.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Michael Grosser
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2013-11-07 00:00:00.000000000 Z
11
+ date: 2013-11-25 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: parallel
@@ -50,6 +50,8 @@ files:
50
50
  - lib/parallel_tests/cli.rb
51
51
  - lib/parallel_tests/cucumber/failures_logger.rb
52
52
  - lib/parallel_tests/cucumber/runner.rb
53
+ - lib/parallel_tests/cucumber/scenario_line_logger.rb
54
+ - lib/parallel_tests/cucumber/scenarios.rb
53
55
  - lib/parallel_tests/gherkin/io.rb
54
56
  - lib/parallel_tests/gherkin/listener.rb
55
57
  - lib/parallel_tests/gherkin/runner.rb
@@ -71,6 +73,7 @@ files:
71
73
  - spec/parallel_tests/cli_spec.rb
72
74
  - spec/parallel_tests/cucumber/failure_logger_spec.rb
73
75
  - spec/parallel_tests/cucumber/runner_spec.rb
76
+ - spec/parallel_tests/cucumber/scenarios_spec.rb
74
77
  - spec/parallel_tests/gherkin/listener_spec.rb
75
78
  - spec/parallel_tests/gherkin/runner_behaviour.rb
76
79
  - spec/parallel_tests/grouper_spec.rb
@@ -104,7 +107,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
104
107
  version: '0'
105
108
  requirements: []
106
109
  rubyforge_project:
107
- rubygems_version: 2.0.6
110
+ rubygems_version: 2.0.3
108
111
  signing_key:
109
112
  specification_version: 4
110
113
  summary: Run Test::Unit / RSpec / Cucumber / Spinach in parallel