parallel_tests 0.16.3 → 0.16.4

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