cukeforker 0.2.1 → 0.2.2

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: c97c06d29ce5a9948bf8cd30b8a7a8685aee2596
4
- data.tar.gz: 8b9f43ba7f53e6501a896fd924d39812e1392440
3
+ metadata.gz: becd9202bf711742b3c2641599a388314744fc13
4
+ data.tar.gz: 8c2897ef60b92f651693ef0591ded68337fffd5f
5
5
  SHA512:
6
- metadata.gz: 192e850138726137effab9b5cc07e8149dd0b1730b9eb19a27aa9ed9ee3fc04a253938c2e1e9ffe776d3ce153a1892b3805dd96d932303ad85731c98ae84d2e2
7
- data.tar.gz: 26639c5e02f9dc75e28748880897d928be38a9501351dbfaa7fd2763cfe7d030f95983c01177df49e35f08b04a97d73a1f659b73f327765b3485014b60fa2cad
6
+ metadata.gz: 2e83d8b780b6fa2540fd13d53e19474e6310916881963e950a77a77af32f2e1603ff3cb6207a2303171b4a8a5725f45026a184e6e245869389acc9adf3267583
7
+ data.tar.gz: 1845ce7c0b69cafabadd56b36362080cd52ff2e3328a1a523c325d2762ff4885eb6a569d967fb21f4297320d195a23fd01430cdc552d472f15aedd328b51b0fe
data/.gitignore CHANGED
@@ -5,4 +5,5 @@ Gemfile.lock
5
5
  \#*
6
6
  .\#*
7
7
  .idea
8
- .ruby-version
8
+ .ruby-version
9
+ /coverage
@@ -1,12 +1,19 @@
1
- cukeforker
2
- ==========
1
+ # cukeforker
3
2
 
4
3
  Forking cukes and VNC displays.
5
4
 
6
5
  [![Build Status](https://secure.travis-ci.org/jarib/cukeforker.png)](http://travis-ci.org/jarib/cukeforker)
6
+ [![Code Climate](https://codeclimate.com/github/jarib/cukeforker.png)](https://codeclimate.com/github/jarib/cukeforker)
7
+ [![Coverage Status](https://coveralls.io/repos/jarib/cukeforker/badge.png)](https://coveralls.io/r/jarib/cukeforker)
8
+
9
+ ### NB!
10
+
11
+ If you're using cukeforker with selenium-webdriver and Firefox, all versions prior to 2.40 has a bug where custom
12
+ Firefox profiles created in a forked process would not get cleaned up. Please make sure you're using selenium-webdriver >= 2.40
13
+ to avoid this.
14
+
15
+ ## Usage
7
16
 
8
- Usage
9
- =============
10
17
 
11
18
  ```ruby
12
19
  # parallelize per feature
@@ -17,7 +17,7 @@ Gem::Specification.new do |s|
17
17
  s.add_dependency "cucumber", ">= 1.1.5"
18
18
  s.add_dependency "vnctools", ">= 0.0.5"
19
19
  s.add_development_dependency "rspec", "~> 2.5"
20
- s.add_development_dependency "simplecov"
20
+ s.add_development_dependency "coveralls"
21
21
  s.add_development_dependency "rake", "~> 0.9.2"
22
22
 
23
23
  s.files = `git ls-files`.split("\n")
@@ -25,14 +25,15 @@ module CukeForker
25
25
  include Observable
26
26
 
27
27
  DEFAULT_OPTIONS = {
28
- :max => 2,
29
- :vnc => false,
30
- :record => false,
31
- :notify => nil,
32
- :out => Dir.pwd,
33
- :log => true,
34
- :format => :html,
35
- :delay => 0
28
+ :max => 2,
29
+ :vnc => false,
30
+ :record => false,
31
+ :notify => nil,
32
+ :out => Dir.pwd,
33
+ :log => true,
34
+ :format => :html,
35
+ :delay => 0,
36
+ :fail_fast => false,
36
37
  }
37
38
 
38
39
  def self.run(features, opts = {})
@@ -48,6 +49,7 @@ module CukeForker
48
49
  listeners = Array(opts[:notify])
49
50
  extra_args = Array(opts[:extra_args])
50
51
  delay = opts[:delay]
52
+ fail_fast = opts[:fail_fast]
51
53
 
52
54
  if opts[:log]
53
55
  listeners << LoggingListener.new
@@ -73,7 +75,7 @@ module CukeForker
73
75
  end
74
76
  end
75
77
 
76
- queue = WorkerQueue.new max, delay
78
+ queue = WorkerQueue.new(max, delay, fail_fast)
77
79
  features.each do |feature|
78
80
  queue.add Worker.new(feature, format, out, extra_args)
79
81
  end
@@ -1,3 +1,3 @@
1
1
  module CukeForker
2
- VERSION = "0.2.1"
2
+ VERSION = "0.2.2"
3
3
  end
@@ -3,9 +3,9 @@ module CukeForker
3
3
  include Observable
4
4
 
5
5
  class << self
6
- attr_writer :id
7
- def id; @id ||= -1; end
8
- end
6
+ attr_writer :id
7
+ def id; @id ||= -1; end
8
+ end
9
9
 
10
10
  attr_reader :status, :feature, :pid, :format, :out, :id, :data
11
11
 
@@ -40,10 +40,9 @@ module CukeForker
40
40
  end
41
41
 
42
42
  def args
43
- args = %W[--format #{format} --out #{output}]
43
+ args = Array(format).flat_map { |f| %W[--format #{f} --out #{output(f)}] }
44
44
  args += @extra_args
45
45
  args << feature
46
-
47
46
  args
48
47
  end
49
48
 
@@ -57,7 +56,8 @@ module CukeForker
57
56
  ]"
58
57
  end
59
58
 
60
- def output
59
+ def output(format=nil)
60
+ format = @format if format.nil?
61
61
  File.join out, "#{basename}.#{format}"
62
62
  end
63
63
 
@@ -73,6 +73,15 @@ module CukeForker
73
73
  @basename ||= feature.gsub(/\W/, '_')
74
74
  end
75
75
 
76
+ def kill
77
+ return unless pid
78
+
79
+ Process.kill("TERM", pid)
80
+ Process.wait(pid)
81
+ rescue
82
+ # could not kill worker, ignore
83
+ end
84
+
76
85
  private
77
86
 
78
87
  def execute_cucumber
@@ -2,9 +2,10 @@ module CukeForker
2
2
  class WorkerQueue
3
3
  include Observable
4
4
 
5
- def initialize(max, delay)
5
+ def initialize(max, delay, fail_fast=false)
6
6
  @max = max
7
7
  @delay = delay
8
+ @fail_fast = fail_fast
8
9
 
9
10
  if @max < 0
10
11
  raise ArgumentError, "max workers cannot be negative, got #{@max.inspect}"
@@ -121,6 +122,12 @@ module CukeForker
121
122
  @running.delete worker
122
123
  @finished << worker
123
124
 
125
+ if @fail_fast && worker.failed?
126
+ @pending.clear
127
+ @running.each { |w| w.kill }
128
+ @running.clear
129
+ end
130
+
124
131
  fire :on_worker_finished, worker
125
132
  end
126
133
 
@@ -14,13 +14,14 @@ module CukeForker
14
14
  log = false
15
15
  features = %w[a b]
16
16
  delay = 1
17
+ fail_fast = false
17
18
 
18
19
  mock_queue = double(WorkerQueue)
19
20
  mock_workers = Array.new(2) { |n| double("Worker-#{n}") }
20
21
 
21
22
  Process.stub(:pid => 1234)
22
23
 
23
- WorkerQueue.should_receive(:new).with(max, 1).and_return mock_queue
24
+ WorkerQueue.should_receive(:new).with(max, 1, fail_fast).and_return mock_queue
24
25
  Worker.should_receive(:new).with("a", :json, "/tmp", []).and_return mock_workers[0]
25
26
  Worker.should_receive(:new).with("b", :json, "/tmp", []).and_return mock_workers[1]
26
27
 
@@ -29,12 +30,13 @@ module CukeForker
29
30
  mock_queue.should_receive(:add).with mock_workers[1]
30
31
 
31
32
  Runner.create(features,
32
- :max => max,
33
- :notify => listeners,
34
- :format => format,
35
- :log => false,
36
- :out => out,
37
- :delay => 1
33
+ :max => max,
34
+ :notify => listeners,
35
+ :format => format,
36
+ :log => false,
37
+ :out => out,
38
+ :delay => 1,
39
+ :fail_fast => fail_fast,
38
40
  ).should be_kind_of(Runner)
39
41
  end
40
42
 
@@ -3,7 +3,8 @@ require File.expand_path("../../spec_helper", __FILE__)
3
3
  module CukeForker
4
4
  describe WorkerQueue do
5
5
  let(:workers) { Array.new(5) { |n| double("Worker-#{n}") } }
6
- let(:queue) { WorkerQueue.new(3, 0) }
6
+ let(:queue) { WorkerQueue.new(3, 0, false) }
7
+
7
8
 
8
9
  it "adds an item to the queue" do
9
10
  queue.should_not be_backed_up
@@ -50,9 +51,9 @@ module CukeForker
50
51
 
51
52
  queue.fill
52
53
 
53
- workers[0].stub(:finished? => true)
54
- workers[1].stub(:finished? => true)
55
- workers[2].stub(:finished? => false)
54
+ workers[0].stub(:finished? => true, :failed? => false)
55
+ workers[1].stub(:finished? => true, :failed? => false)
56
+ workers[2].stub(:finished? => false, :failed? => false)
56
57
 
57
58
  queue.poll
58
59
 
@@ -70,9 +71,9 @@ module CukeForker
70
71
 
71
72
  workers.each { |w| queue.add w }
72
73
 
73
- workers[0].stub(:start => nil, :finished? => true)
74
- workers[1].stub(:start => nil, :finished? => true)
75
- workers[2].stub(:start => nil, :finished? => false)
74
+ workers[0].stub(:start => nil, :finished? => true, :failed? => false)
75
+ workers[1].stub(:start => nil, :finished? => true, :failed? => false)
76
+ workers[2].stub(:start => nil, :finished? => false, :failed? => false)
76
77
 
77
78
  listener.should_receive(:on_worker_starting).exactly(3).times
78
79
  queue.fill
@@ -124,9 +125,9 @@ module CukeForker
124
125
  queue.stub :start_time => Time.now
125
126
  workers[0..2].each { |w| queue.add w }
126
127
 
127
- workers[0].stub(:start => nil)
128
- workers[1].stub(:start => nil)
129
- workers[2].stub(:start => nil)
128
+ workers[0].stub(:start => nil, :failed? => false)
129
+ workers[1].stub(:start => nil, :failed? => false)
130
+ workers[2].stub(:start => nil, :failed? => false)
130
131
 
131
132
  workers[0].should_receive(:finished?).twice.and_return false, true
132
133
  workers[1].should_receive(:finished?).twice.and_return false, true
@@ -148,13 +149,45 @@ module CukeForker
148
149
 
149
150
  workers[0..2].each { |w| queue.add w }
150
151
 
151
- workers[0].stub(:start => nil, :finished? => true)
152
- workers[1].stub(:start => nil, :finished? => false)
153
- workers[2].stub(:start => nil, :finished? => false)
152
+ workers[0].stub(:start => nil, :finished? => true, :failed? => false)
153
+ workers[1].stub(:start => nil, :finished? => false, :failed? => false)
154
+ workers[2].stub(:start => nil, :finished? => false, :failed? => false)
154
155
 
155
156
  queue.fill
156
157
  queue.poll
157
158
  queue.eta.should == [Time.now + seconds_per_child*2, 2, 1]
158
159
  end
159
- end # WorkerQueue
160
+
161
+ context "with fail fast enabled" do
162
+ let(:workers) { Array.new(10) { |n| double("Worker-#{n}") } }
163
+ let(:queue) { WorkerQueue.new(3, 0, true) }
164
+
165
+ it "should exit after the first test failure" do
166
+ queue.should be_empty
167
+
168
+ workers.each { |w| queue.add w }
169
+
170
+ workers[0].stub(:start => nil, :finished? => true, :failed? => false)
171
+ workers[1].stub(:start => nil, :finished? => false, :failed? => false, :kill => nil)
172
+ workers[2].stub(:start => nil, :finished? => false, :failed? => false, :kill => nil)
173
+ queue.fill
174
+ queue.poll
175
+
176
+ workers[3].stub(:start => nil, :finished? => false, :failed? => true)
177
+ queue.fill
178
+ queue.poll
179
+
180
+ workers[3].stub(:finished? => true)
181
+ queue.fill
182
+ queue.poll
183
+
184
+ queue.should_not be_backed_up
185
+ queue.should be_empty
186
+ queue.instance_variable_get(:@finished).should == [ workers[0], workers[3] ]
187
+
188
+ queue.should have_failures
189
+ end
190
+ end
191
+
192
+ end # WorkerQueue
160
193
  end # CukeForker
@@ -25,6 +25,19 @@ module CukeForker
25
25
  end
26
26
  end
27
27
 
28
+ context "running a scenario with multiple report formats" do
29
+ formats = [ :json, :junit ]
30
+ path = "some/path"
31
+ let(:worker) { Worker.new("some/feature:51", formats, path) }
32
+
33
+ it "has an output file for each format specified" do
34
+ expected_args = formats.flat_map do |f|
35
+ %W[--format #{f} --out #{path}/some_feature_51.#{f}]
36
+ end
37
+ worker.args.each_cons(expected_args.size).include?(expected_args).should be_true
38
+ end
39
+ end
40
+
28
41
  it "creates an argument string based on the given parameters" do
29
42
  worker.args.should == %w{--format json --out some/path/some_feature.json --extra args some/feature }
30
43
  end
@@ -115,5 +128,22 @@ module CukeForker
115
128
  Process.stub(:waitpid2).and_raise(Errno::ESRCH)
116
129
  worker.should be_finished
117
130
  end
131
+
132
+ it "can kill the child process" do
133
+ worker.stub(:pid => $$)
134
+
135
+ Process.should_receive(:kill)
136
+ Process.should_receive(:wait)
137
+
138
+ worker.kill
139
+ end
140
+
141
+ it "ignores failures when killing the child" do
142
+ worker.stub(:pid => $$)
143
+
144
+ Process.should_receive(:kill).and_raise(Errno::ECHILD)
145
+ worker.kill.should be_nil
146
+ end
147
+
118
148
  end # Worker
119
149
  end # CukeForker
@@ -1,10 +1,5 @@
1
- if ENV['COVERAGE']
2
- raise "simplecov only works on 1.9" unless RUBY_PLATFORM >= "1.9"
3
- require 'simplecov'
4
- SimpleCov.start {
5
- add_filter "spec/"
6
- }
7
- end
1
+ require 'coveralls'
2
+ Coveralls.wear!
8
3
 
9
4
  $LOAD_PATH.unshift File.expand_path("../lib")
10
5
  require 'cukeforker'
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: cukeforker
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.1
4
+ version: 0.2.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jari Bakken
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-01-16 00:00:00.000000000 Z
11
+ date: 2014-09-09 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: cucumber
@@ -53,7 +53,7 @@ dependencies:
53
53
  - !ruby/object:Gem::Version
54
54
  version: '2.5'
55
55
  - !ruby/object:Gem::Dependency
56
- name: simplecov
56
+ name: coveralls
57
57
  requirement: !ruby/object:Gem::Requirement
58
58
  requirements:
59
59
  - - '>='
@@ -138,7 +138,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
138
138
  version: '0'
139
139
  requirements: []
140
140
  rubyforge_project: cukeforker
141
- rubygems_version: 2.1.10
141
+ rubygems_version: 2.0.14
142
142
  signing_key:
143
143
  specification_version: 4
144
144
  summary: Library to maintain a forking queue of Cucumber processes
@@ -152,4 +152,3 @@ test_files:
152
152
  - spec/cukeforker/worker_queue_spec.rb
153
153
  - spec/cukeforker/worker_spec.rb
154
154
  - spec/spec_helper.rb
155
- has_rdoc: