specjour 0.2.5 → 0.3.0.rc1

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.
Files changed (40) hide show
  1. data/History.markdown +51 -20
  2. data/README.markdown +53 -26
  3. data/Rakefile +3 -5
  4. data/VERSION +1 -1
  5. data/bin/specjour +1 -48
  6. data/lib/specjour/cli.rb +97 -0
  7. data/lib/specjour/configuration.rb +73 -0
  8. data/lib/specjour/connection.rb +1 -1
  9. data/lib/specjour/cucumber/distributed_formatter.rb +2 -5
  10. data/lib/specjour/cucumber/preloader.rb +13 -0
  11. data/lib/specjour/cucumber.rb +3 -2
  12. data/lib/specjour/db_scrub.rb +8 -1
  13. data/lib/specjour/dispatcher.rb +99 -36
  14. data/lib/specjour/manager.rb +63 -37
  15. data/lib/specjour/printer.rb +33 -11
  16. data/lib/specjour/quiet_fork.rb +11 -0
  17. data/lib/specjour/rspec/distributed_formatter.rb +4 -15
  18. data/lib/specjour/rspec/preloader.rb +8 -0
  19. data/lib/specjour/rspec.rb +1 -0
  20. data/lib/specjour/rsync_daemon.rb +1 -1
  21. data/lib/specjour/socket_helper.rb +28 -0
  22. data/lib/specjour/worker.rb +42 -25
  23. data/lib/specjour.rb +13 -5
  24. data/spec/spec_helper.rb +12 -0
  25. data/spec/specjour/cli_spec.rb +104 -0
  26. data/spec/specjour/configuration_spec.rb +112 -0
  27. data/spec/{cpu_spec.rb → specjour/cpu_spec.rb} +0 -0
  28. data/spec/{manager_spec.rb → specjour/manager_spec.rb} +2 -2
  29. data/spec/specjour/printer_spec.rb +101 -0
  30. data/spec/{rsync_daemon_spec.rb → specjour/rsync_daemon_spec.rb} +2 -0
  31. data/spec/specjour_spec.rb +13 -2
  32. data/specjour.gemspec +33 -26
  33. metadata +69 -31
  34. data/lib/specjour/cucumber/dispatcher.rb +0 -18
  35. data/lib/specjour/cucumber/printer.rb +0 -9
  36. data/lib/specjour/socket_helpers.rb +0 -11
  37. data/lib/specjour/tasks/dispatch.rake +0 -21
  38. data/lib/specjour/tasks/specjour.rb +0 -1
  39. data/rails/init.rb +0 -6
  40. data/spec/lib/specjour/worker_spec.rb +0 -14
data/lib/specjour.rb CHANGED
@@ -7,32 +7,35 @@ autoload :Timeout, 'timeout'
7
7
  autoload :Benchmark, 'benchmark'
8
8
  autoload :Logger, 'logger'
9
9
  autoload :Socket, 'socket'
10
+ autoload :StringIO, 'stringio'
10
11
 
11
12
  module Specjour
13
+ autoload :CLI, 'specjour/cli'
12
14
  autoload :CPU, 'specjour/cpu'
15
+ autoload :Configuration, 'specjour/configuration'
13
16
  autoload :Connection, 'specjour/connection'
17
+ autoload :DbScrub, 'specjour/db_scrub'
14
18
  autoload :Dispatcher, 'specjour/dispatcher'
15
19
  autoload :Manager, 'specjour/manager'
16
20
  autoload :OpenStruct, 'ostruct'
17
21
  autoload :Printer, 'specjour/printer'
18
22
  autoload :Protocol, 'specjour/protocol'
23
+ autoload :QuietFork, 'specjour/quiet_fork'
19
24
  autoload :RsyncDaemon, 'specjour/rsync_daemon'
20
- autoload :SocketHelpers, 'specjour/socket_helpers'
25
+ autoload :SocketHelper, 'specjour/socket_helper'
21
26
  autoload :Worker, 'specjour/worker'
22
27
 
23
28
  autoload :Cucumber, 'specjour/cucumber'
24
29
  autoload :Rspec, 'specjour/rspec'
25
30
 
26
- VERSION = "0.2.5".freeze
27
-
28
- class Error < StandardError; end
31
+ VERSION = "0.3.0.rc1".freeze
29
32
 
30
33
  def self.logger
31
34
  @logger ||= new_logger
32
35
  end
33
36
 
34
37
  def self.new_logger(level = Logger::UNKNOWN)
35
- @logger = Logger.new $stdout
38
+ @logger = Logger.new $stderr
36
39
  @logger.level = level
37
40
  @logger
38
41
  end
@@ -40,4 +43,9 @@ module Specjour
40
43
  def self.log?
41
44
  logger.level != Logger::UNKNOWN
42
45
  end
46
+
47
+ Error = Class.new(StandardError)
48
+ PROGRAM_NAME = $PROGRAM_NAME # keep a reference of the original program name
49
+
50
+ GC.copy_on_write_friendly = true if GC.respond_to?(:copy_on_write_friendly=)
43
51
  end
data/spec/spec_helper.rb CHANGED
@@ -3,6 +3,18 @@ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
3
3
  require 'specjour'
4
4
  require 'spec/autorun'
5
5
 
6
+ class NullObject
7
+ def method_missing(name, *args)
8
+ self
9
+ end
10
+ end
11
+
12
+ begin
13
+ Specjour::DbScrub
14
+ rescue LoadError
15
+ $stderr.puts "DbScrub failed to load properly, that's okay though"
16
+ end
17
+
6
18
  Spec::Runner.configure do |config|
7
19
  config.mock_with :rr
8
20
  end
@@ -0,0 +1,104 @@
1
+ require 'spec_helper'
2
+
3
+ describe Specjour::CLI do
4
+ let(:fake_pid) { 100_000_000 }
5
+ before do
6
+ stub(Specjour::CPU).cores.returns(27)
7
+ stub(Specjour::Dispatcher).new.returns(stub!)
8
+ stub(Specjour::Manager).new.returns(stub!)
9
+ stub(Specjour::Worker).new.returns(stub!)
10
+ end
11
+
12
+ describe "#listen" do
13
+ let(:manager) { NullObject.new }
14
+
15
+ before do
16
+ stub(Dir).pwd { '/home/someone/foo-bar' }
17
+ end
18
+
19
+ def manager_receives_options(options)
20
+ expected_options = hash_including(options)
21
+ mock(Specjour::Manager).new(expected_options).returns(manager)
22
+ end
23
+
24
+ it "defaults workers to system cores" do
25
+ manager_receives_options("worker_size" => 27)
26
+ Specjour::CLI.start %w(listen -p none)
27
+ end
28
+
29
+ it "accepts an array of projects to listen to" do
30
+ manager_receives_options("registered_projects" => %w(one two three))
31
+ Specjour::CLI.start %w(listen --projects one two three)
32
+ end
33
+
34
+ it "listens to the current path by default" do
35
+ manager_receives_options("registered_projects" => %w(foo-bar))
36
+ Specjour::CLI.start %w(listen)
37
+ end
38
+ end
39
+
40
+ describe "#dispatch" do
41
+ let(:dispatcher) { NullObject.new }
42
+
43
+ def dispatcher_receives_options(options)
44
+ expected_options = hash_including(options)
45
+ mock(Specjour::Dispatcher).new(expected_options).returns(dispatcher)
46
+ end
47
+
48
+ it "defaults path to the current directory" do
49
+ stub(Dir).pwd.returns("eh")
50
+ dispatcher_receives_options("project_path" => "eh")
51
+ Specjour::CLI.start %w(dispatch)
52
+ end
53
+
54
+ it "defaults workers to system cores" do
55
+ dispatcher_receives_options("worker_size" => 27)
56
+ Specjour::CLI.start %w(dispatch)
57
+ end
58
+
59
+ it "accepts a project alias" do
60
+ dispatcher_receives_options("project_alias" => "eh")
61
+ Specjour::CLI.start %w(dispatch --alias eh)
62
+ end
63
+ end
64
+
65
+ describe "#work" do
66
+ it "starts a worker with the required parameters" do
67
+ worker = NullObject.new
68
+ args = {'project_path' => "eh", 'printer_uri' => "specjour://1.1.1.1:12345", 'number' => 1, 'task' => 'run_tests'}
69
+ mock(Specjour::Worker).new(hash_including(args)).returns(worker)
70
+ Specjour::CLI.start %w(work --project-path eh --printer-uri specjour://1.1.1.1:12345 --number 1 --task run_tests)
71
+ end
72
+ end
73
+
74
+ describe "#handle_logging" do
75
+ before do
76
+ stub(subject).options.returns({})
77
+ end
78
+
79
+ it "enables logging" do
80
+ subject.options['log'] = true
81
+ mock(Specjour).new_logger(Logger::DEBUG).returns(stub!)
82
+ subject.send(:handle_logging)
83
+ end
84
+
85
+ it "doesn't enable logging" do
86
+ dont_allow(Specjour).new_logger
87
+ subject.send(:handle_logging)
88
+ end
89
+ end
90
+
91
+ describe "#prepare" do
92
+ let(:dispatcher) { NullObject.new }
93
+
94
+ def dispatcher_receives_options(options)
95
+ expected_options = hash_including(options)
96
+ mock(Specjour::Dispatcher).new(expected_options).returns(dispatcher)
97
+ end
98
+
99
+ it "sets the worker task to 'prepare'" do
100
+ dispatcher_receives_options("worker_task" => "prepare")
101
+ Specjour::CLI.start %w(prepare)
102
+ end
103
+ end
104
+ end
@@ -0,0 +1,112 @@
1
+ require 'spec_helper'
2
+
3
+ module RailsAndActiveRecordDefined
4
+ def self.extended(base)
5
+ base.class_eval do
6
+ before do
7
+ Object.const_set(:Rails, Module.new)
8
+ Object.const_set(:ActiveRecord, Module.new)
9
+ ActiveRecord.const_set(:Base, Class.new)
10
+ end
11
+
12
+ after do
13
+ Object.send(:remove_const, :ActiveRecord)
14
+ Object.send(:remove_const, :Rails)
15
+ end
16
+ end
17
+ end
18
+ end
19
+
20
+ describe Specjour::Configuration do
21
+ subject do
22
+ Specjour::Configuration
23
+ end
24
+
25
+ before { subject.reset }
26
+
27
+ describe "#before_fork" do
28
+ context "default proc" do
29
+ context "ActiveRecord defined" do
30
+ extend RailsAndActiveRecordDefined
31
+ it "disconnects from the database" do
32
+ mock(ActiveRecord::Base).remove_connection
33
+ subject.before_fork.call
34
+ end
35
+ end
36
+
37
+ context "bundler installed" do
38
+ before do
39
+ mock(subject).system("which bundle") { true }
40
+ end
41
+
42
+ context "when gems not satisfied" do
43
+ before do
44
+ mock(subject).system("bundle check") { false }
45
+ end
46
+
47
+ it "runs 'bundle install'" do
48
+ mock(subject).system('bundle install')
49
+ subject.before_fork.call
50
+ end
51
+ end
52
+
53
+ context "when gems are satisfied" do
54
+ before do
55
+ mock(subject).system("bundle check") { true }
56
+ end
57
+
58
+ it "doesn't run 'bundle install'" do
59
+ dont_allow(subject).system('bundle install')
60
+ subject.before_fork.call
61
+ end
62
+ end
63
+ end
64
+ end
65
+
66
+ context "custom proc" do
67
+ it "runs block" do
68
+ subject.before_fork = lambda { :custom_before }
69
+ subject.before_fork.call.should == :custom_before
70
+ end
71
+ end
72
+ end
73
+
74
+ describe "#after_fork" do
75
+ it "defaults to nothing" do
76
+ subject.after_fork.call.should be_nil
77
+ end
78
+
79
+ it "runs the block" do
80
+ subject.after_fork = lambda { :custom_after }
81
+ subject.after_fork.call.should == :custom_after
82
+ end
83
+
84
+ context "ActiveRecord defined" do
85
+ extend RailsAndActiveRecordDefined
86
+ it "scrubs the db" do
87
+ mock(Specjour::DbScrub).scrub
88
+ subject.after_fork.call
89
+ end
90
+ end
91
+ end
92
+
93
+ describe "#prepare" do
94
+ it "defaults to nothing" do
95
+ subject.prepare.call.should be_nil
96
+ end
97
+
98
+ it "runs the block" do
99
+ subject.prepare = lambda { :custom_preparation }
100
+ subject.prepare.call.should == :custom_preparation
101
+ end
102
+
103
+ context "ActiveRecord defined" do
104
+ extend RailsAndActiveRecordDefined
105
+ it "drops then scrubs the db" do
106
+ mock(Specjour::DbScrub).drop
107
+ mock(Specjour::DbScrub).scrub
108
+ subject.prepare.call
109
+ end
110
+ end
111
+ end
112
+ end
File without changes
@@ -2,8 +2,8 @@ require 'spec_helper'
2
2
 
3
3
  describe Specjour::Manager do
4
4
  describe "#available_for?" do
5
- it "is available for all projects by default" do
6
- subject.available_for?(rand.to_s).should be_true
5
+ it "isn't available for all projects by default" do
6
+ subject.available_for?(rand.to_s).should be_false
7
7
  end
8
8
 
9
9
  it "is available for one project" do
@@ -0,0 +1,101 @@
1
+ require 'spec_helper'
2
+
3
+ describe Specjour::Printer do
4
+ subject do
5
+ Specjour::Printer.new []
6
+ end
7
+
8
+ describe "#exit_status" do
9
+ let(:rspec_report) { Object.new }
10
+ let(:cucumber_report) { Object.new }
11
+
12
+ context "when cucumber_report is nil" do
13
+ context "and rspec_report has true exit status" do
14
+ before do
15
+ stub(rspec_report).exit_status { true }
16
+ subject.instance_variable_set(:@rspec_report, rspec_report)
17
+ end
18
+
19
+ it "has a true exit status" do
20
+ subject.exit_status.should be_true
21
+ end
22
+ end
23
+
24
+ context "and rspec_report has false exit status" do
25
+ before do
26
+ stub(rspec_report).exit_status { false }
27
+ subject.instance_variable_set(:@rspec_report, rspec_report)
28
+ end
29
+
30
+ it "has a true exit status" do
31
+ subject.exit_status.should be_false
32
+ end
33
+ end
34
+ end
35
+
36
+ context "when rspec report is nil" do
37
+ context "and cucumber_report has true exit status" do
38
+ before do
39
+ stub(cucumber_report).exit_status { true }
40
+ subject.instance_variable_set(:@cucumber_report, cucumber_report)
41
+ end
42
+
43
+ it "has a true exit status" do
44
+ subject.exit_status.should be_true
45
+ end
46
+ end
47
+
48
+ context "and cucumber_report has false exit status" do
49
+ before do
50
+ stub(cucumber_report).exit_status { false }
51
+ subject.instance_variable_set(:@cucumber_report, cucumber_report)
52
+ end
53
+
54
+ it "has a true exit status" do
55
+ subject.exit_status.should be_false
56
+ end
57
+ end
58
+ end
59
+
60
+ context "when both rspec and cucumber reports exists" do
61
+ context "and rspec exit status is false" do
62
+ before do
63
+ stub(rspec_report).exit_status { false }
64
+ stub(cucumber_report).exit_status { true }
65
+ subject.instance_variable_set(:@cucumber_report, cucumber_report)
66
+ subject.instance_variable_set(:@rspec_report, rspec_report)
67
+ end
68
+
69
+ it "returns false" do
70
+ subject.exit_status.should be_false
71
+ end
72
+ end
73
+
74
+ context "and cucumber exit status is false" do
75
+ before do
76
+ stub(rspec_report).exit_status { true }
77
+ stub(cucumber_report).exit_status { false }
78
+ subject.instance_variable_set(:@cucumber_report, cucumber_report)
79
+ subject.instance_variable_set(:@rspec_report, rspec_report)
80
+ end
81
+
82
+ it "returns false" do
83
+ subject.exit_status.should be_false
84
+ end
85
+ end
86
+
87
+ context "both cucumber and rspec exit status are true" do
88
+ before do
89
+ stub(rspec_report).exit_status { true }
90
+ stub(cucumber_report).exit_status { true }
91
+ subject.instance_variable_set(:@cucumber_report, cucumber_report)
92
+ subject.instance_variable_set(:@rspec_report, rspec_report)
93
+ end
94
+
95
+ it "returns false" do
96
+ subject.exit_status.should be_true
97
+ end
98
+ end
99
+ end
100
+ end
101
+ end
@@ -11,6 +11,8 @@ describe Specjour::RsyncDaemon do
11
11
  stub(Dir).chdir
12
12
  stub(File).open
13
13
  stub(File).read
14
+ stub(FileUtils).rm
15
+ stub(Process).kill
14
16
  end
15
17
 
16
18
  specify { subject.config_directory.should == '/tmp/seasonal/.specjour' }
@@ -1,5 +1,16 @@
1
- require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
1
+ require 'spec_helper'
2
+
3
+ class CustomException < RuntimeError
4
+ end
5
+
6
+ def boo
7
+ raise CustomException, 'fails'
8
+ end
2
9
 
3
10
  describe Specjour do
4
- it "lives"
11
+ it "pends as an example"
12
+
13
+ it "fails as an example" do
14
+ boo
15
+ end
5
16
  end
data/specjour.gemspec CHANGED
@@ -5,11 +5,11 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = %q{specjour}
8
- s.version = "0.2.5"
8
+ s.version = "0.3.0.rc1"
9
9
 
10
- s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
10
+ s.required_rubygems_version = Gem::Requirement.new("> 1.3.1") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["Sandro Turriate"]
12
- s.date = %q{2010-05-13}
12
+ s.date = %q{2010-07-12}
13
13
  s.default_executable = %q{specjour}
14
14
  s.description = %q{Distribute your spec suite amongst your LAN via Bonjour.}
15
15
  s.email = %q{sandro.turriate@gmail.com}
@@ -28,48 +28,52 @@ Gem::Specification.new do |s|
28
28
  "VERSION",
29
29
  "bin/specjour",
30
30
  "lib/specjour.rb",
31
+ "lib/specjour/cli.rb",
32
+ "lib/specjour/configuration.rb",
31
33
  "lib/specjour/connection.rb",
32
34
  "lib/specjour/cpu.rb",
33
35
  "lib/specjour/cucumber.rb",
34
- "lib/specjour/cucumber/dispatcher.rb",
35
36
  "lib/specjour/cucumber/distributed_formatter.rb",
36
37
  "lib/specjour/cucumber/final_report.rb",
37
- "lib/specjour/cucumber/printer.rb",
38
+ "lib/specjour/cucumber/preloader.rb",
38
39
  "lib/specjour/db_scrub.rb",
39
40
  "lib/specjour/dispatcher.rb",
40
41
  "lib/specjour/manager.rb",
41
42
  "lib/specjour/printer.rb",
42
43
  "lib/specjour/protocol.rb",
44
+ "lib/specjour/quiet_fork.rb",
43
45
  "lib/specjour/rspec.rb",
44
46
  "lib/specjour/rspec/distributed_formatter.rb",
45
47
  "lib/specjour/rspec/final_report.rb",
46
48
  "lib/specjour/rspec/marshalable_rspec_failure.rb",
49
+ "lib/specjour/rspec/preloader.rb",
47
50
  "lib/specjour/rsync_daemon.rb",
48
- "lib/specjour/socket_helpers.rb",
49
- "lib/specjour/tasks/dispatch.rake",
50
- "lib/specjour/tasks/specjour.rb",
51
+ "lib/specjour/socket_helper.rb",
51
52
  "lib/specjour/worker.rb",
52
- "rails/init.rb",
53
- "spec/cpu_spec.rb",
54
- "spec/lib/specjour/worker_spec.rb",
55
- "spec/manager_spec.rb",
56
- "spec/rsync_daemon_spec.rb",
57
53
  "spec/spec.opts",
58
54
  "spec/spec_helper.rb",
55
+ "spec/specjour/cli_spec.rb",
56
+ "spec/specjour/configuration_spec.rb",
57
+ "spec/specjour/cpu_spec.rb",
58
+ "spec/specjour/manager_spec.rb",
59
+ "spec/specjour/printer_spec.rb",
60
+ "spec/specjour/rsync_daemon_spec.rb",
59
61
  "spec/specjour_spec.rb",
60
62
  "specjour.gemspec"
61
63
  ]
62
64
  s.homepage = %q{http://github.com/sandro/specjour}
63
65
  s.rdoc_options = ["--charset=UTF-8"]
64
66
  s.require_paths = ["lib"]
65
- s.rubygems_version = %q{1.3.6}
67
+ s.rubygems_version = %q{1.3.7}
66
68
  s.summary = %q{Distribute your spec suite amongst your LAN via Bonjour.}
67
69
  s.test_files = [
68
- "spec/cpu_spec.rb",
69
- "spec/lib/specjour/worker_spec.rb",
70
- "spec/manager_spec.rb",
71
- "spec/rsync_daemon_spec.rb",
72
- "spec/spec_helper.rb",
70
+ "spec/spec_helper.rb",
71
+ "spec/specjour/cli_spec.rb",
72
+ "spec/specjour/configuration_spec.rb",
73
+ "spec/specjour/cpu_spec.rb",
74
+ "spec/specjour/manager_spec.rb",
75
+ "spec/specjour/printer_spec.rb",
76
+ "spec/specjour/rsync_daemon_spec.rb",
73
77
  "spec/specjour_spec.rb"
74
78
  ]
75
79
 
@@ -77,25 +81,28 @@ Gem::Specification.new do |s|
77
81
  current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
78
82
  s.specification_version = 3
79
83
 
80
- if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
84
+ if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
81
85
  s.add_runtime_dependency(%q<dnssd>, ["= 1.3.1"])
82
86
  s.add_runtime_dependency(%q<rspec>, [">= 0"])
87
+ s.add_runtime_dependency(%q<thor>, ["= 0.13.6"])
83
88
  s.add_development_dependency(%q<rspec>, ["= 1.3.0"])
84
- s.add_development_dependency(%q<rr>, ["= 0.10.11"])
85
- s.add_development_dependency(%q<yard>, ["= 0.5.3"])
89
+ s.add_development_dependency(%q<rr>, [">= 0.10.11"])
90
+ s.add_development_dependency(%q<yard>, [">= 0.5.3"])
86
91
  else
87
92
  s.add_dependency(%q<dnssd>, ["= 1.3.1"])
88
93
  s.add_dependency(%q<rspec>, [">= 0"])
94
+ s.add_dependency(%q<thor>, ["= 0.13.6"])
89
95
  s.add_dependency(%q<rspec>, ["= 1.3.0"])
90
- s.add_dependency(%q<rr>, ["= 0.10.11"])
91
- s.add_dependency(%q<yard>, ["= 0.5.3"])
96
+ s.add_dependency(%q<rr>, [">= 0.10.11"])
97
+ s.add_dependency(%q<yard>, [">= 0.5.3"])
92
98
  end
93
99
  else
94
100
  s.add_dependency(%q<dnssd>, ["= 1.3.1"])
95
101
  s.add_dependency(%q<rspec>, [">= 0"])
102
+ s.add_dependency(%q<thor>, ["= 0.13.6"])
96
103
  s.add_dependency(%q<rspec>, ["= 1.3.0"])
97
- s.add_dependency(%q<rr>, ["= 0.10.11"])
98
- s.add_dependency(%q<yard>, ["= 0.5.3"])
104
+ s.add_dependency(%q<rr>, [">= 0.10.11"])
105
+ s.add_dependency(%q<yard>, [">= 0.5.3"])
99
106
  end
100
107
  end
101
108